diff -u --recursive --new-file v2.4.3/linux/CREDITS linux/CREDITS
--- v2.4.3/linux/CREDITS	Sun Mar 25 18:14:20 2001
+++ linux/CREDITS	Fri Apr 20 16:23:12 2001
@@ -311,9 +311,6 @@
 W: http://samba.org/~anton/
 P: 1024/8462A731 4C 55 86 34 44 59 A7 99  2B 97 88 4A 88 9A 0D 97
 D: sun4 port, Sparc hacker
-S: 47 Robert Street
-S: Marrickville NSW 2204
-S: Australia
 
 N: Hugh Blemings
 E: hugh@misc.nu
@@ -331,6 +328,9 @@
 D: AUN network protocols
 D: Co-architect of the parallel port sharing system
 D: IPv6 netfilter
+S: FutureTV Labs Ltd
+S: Brunswick House, 61-69 Newmarket Rd, Cambridge CB5 8EG
+S: United Kingdom
 
 N: Thomas Bogendörfer
 E: tsbogend@alpha.franken.de
@@ -766,6 +766,11 @@
 S: S-114 53 Stockholm
 S: Sweden
 
+N: Michael Engel
+E: engel@unix-ag.org
+D: DECstation framebuffer drivers
+S: Germany
+
 N: Paal-Kristian Engstad
 E: engstad@intermetrics.com
 D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.)
@@ -1116,8 +1121,8 @@
 E: rth@twiddle.net
 E: rth@cygnus.com
 D: Alpha hacker, kernel and userland
-S: 50 E. Middlefield #10
-S: Mountain View, California 94043
+S: 1668 California St.
+S: Mountain View, California 94041
 S: USA
 
 N: Benjamin Herrenschmidt
@@ -1220,13 +1225,12 @@
 S: USA
 
 N: Harald Hoyer
-E: HarryH@Royal.Net
-W: http://hot.spotline.de/
-W: http://home.pages.de/~saturn
+E: harald.hoyer@parzelle.de
+W: http://parzelle.de/
 D: ip_masq_quake
 D: md boot support
-S: Alleenstrasse 27
-S: D-71679 Asperg
+S: Hohe Strasse 30
+S: D-70176 Stuttgart
 S: Germany
 
 N: Jan Hubicka
@@ -1479,8 +1483,9 @@
 D: 6pack driver for AX.25
 
 N: Harald Koerfgen
-E: harald@unix-ag.org
-D: DECstation port
+E: hkoerfg@web.de
+D: Linux/MIPS kernel hacks and fixes,
+D: DECstation port, Sharp Mobilon port
 S: D-50931 Koeln
 S: Germany
 
@@ -1725,12 +1730,8 @@
 S: Czech Republic
 
 N: Paul Mackerras
-E: paulus@linuxcare.com
+E: paulus@samba.org
 D: Linux port for PCI Power Macintosh
-S: Linuxcare, Inc.
-S: 24 Marcus Clarke Street
-S: Canberra ACT 2601
-S: Australia
 
 N: Pat Mackinlay
 E: pat@it.com.au
@@ -1879,6 +1880,11 @@
 S: 80050-430 - Curitiba - Paraná
 S: Brazil
 
+N: Karsten Merker
+E: merker@linuxtag.org
+D: DECstation framebuffer drivers
+S: Germany
+
 N: Michael Meskes
 E: meskes@debian.org
 P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03  AB AB 15 A3 AE AD 39 7D
@@ -2359,8 +2365,8 @@
 S: Brazil
 
 N: Stephen Rothwell
-E: sfr@linuxcare.com.au
-W: http://linuxcare.com.au/sfr
+E: sfr@canb.auug.org.au
+W: http://www.canb.auug.org.au/~sfr
 P: 1024/BD8C7805 CD A4 9D 01 10 6E 7E 3B  91 88 FA D9 C8 40 AA 02
 D: Boot/setup/build work for setup > 2K
 D: Author, APM driver
@@ -2403,12 +2409,12 @@
 S: Germany
 
 N: Paul `Rusty' Russell
-E: rusty@linuxcare.com
+E: rusty@rustcorp.com.au
 W: http://www.samba.org/netfilter
 D: Ruggedly handsome.
 D: netfilter, ipchains with Michael Neuling.
-S: 301/222 City Walk
-S: Canberra ACT 2601
+S: 52 Moore St
+S: Turner ACT 2612
 S: Australia
 
 N: Bill Ryder
@@ -2429,11 +2435,11 @@
 S: Finland
 
 N: Thomas Sailer
-E: sailer@ife.ee.ethz.ch
+E: t.sailer@alumni.ethz.ch
 E: HB9JNX@HB9W.CHE.EU (packet radio)
 D: hfmodem, Baycom and sound card radio modem driver
-S: Weinbergstrasse 76
-S: 8408 Winterthur
+S: Markusstrasse 18
+S: 8006 Zuerich
 S: Switzerland
 
 N: Robert Sanders
@@ -2516,6 +2522,14 @@
 S: San Jose, California
 S: USA
 
+N: Robert Siemer
+E: Robert.Siemer@gmx.de
+P: 2048/C99A4289 2F DC 17 2E 56 62 01 C8  3D F2 AC 09 F2 E5 DD EE
+D: miroSOUND PCM20 radio RDS driver, ACI rewrite
+S: Klosterweg 28 / i309
+S: 76131 Karlsruhe
+S: Germany
+
 N: Jaspreet Singh
 E: jaspreet@sangoma.com
 W: www.sangoma.com
@@ -2696,7 +2710,7 @@
 
 N: Andrew Tridgell
 E: tridge@samba.org
-W: http://linuxcare.com.au/tridge/
+W: http://samba.org/tridge/
 D: dosemu, networking, samba
 S: 3 Ballow Crescent
 S: MacGregor A.C.T 2615
diff -u --recursive --new-file v2.4.3/linux/Documentation/Changes linux/Documentation/Changes
--- v2.4.3/linux/Documentation/Changes	Tue Mar  6 19:44:34 2001
+++ linux/Documentation/Changes	Wed Apr 11 19:02:27 2001
@@ -31,7 +31,7 @@
 Eine deutsche Version dieser Datei finden Sie unter
 <http://www.stefan-winter.de/Changes-2.4.0.txt>.
 
-Last updated: January 11, 2001
+Last updated: April 6, 2001
 
 Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu).
 
@@ -54,7 +54,7 @@
 o  util-linux             2.10o                   # fdformat --version
 o  modutils               2.4.2                   # insmod -V
 o  e2fsprogs              1.19                    # tune2fs
-o  reiserfsprogs          3.x.0d                  # reiserfsck 2>&1|grep reiserfsprogs
+o  reiserfsprogs          3.x.0j                  # reiserfsck 2>&1|grep reiserfsprogs
 o  pcmcia-cs              3.1.21                  # cardmgr -V
 o  PPP                    2.4.0                   # pppd --version
 o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
@@ -148,7 +148,7 @@
 --------
 
 Upgrade to recent modutils to fix various outstanding bugs which are
-seen more frequently under 2.3.x, and to enable auto-loading of USB
+seen more frequently under 2.4.x, and to enable auto-loading of USB
 modules.  In addition, the layout of modules under
 /lib/modules/`uname -r`/ has been made more sane.  This change also
 requires that you upgrade to a recent modutils.
@@ -227,7 +227,7 @@
 
 The PPP driver has been restructured to support multilink and to
 enable it to operate over diverse media layers.  If you use PPP,
-upgrade pppd to at least 2.4.0b1.
+upgrade pppd to at least 2.4.0.
 
 If you are not using devfs, you must have the device file /dev/ppp
 which can be made by:
@@ -307,16 +307,16 @@
 
 Mkinitrd
 --------
-o  <ftp://rawhide.redhat.com/pub/rawhide/SRPMS/SRPMS/mkinitrd-2.9-1.src.rpm>
+o  <ftp://rawhide.redhat.com/pub/rawhide/SRPMS/SRPMS/>
 
 E2fsprogs
 ---------
-o  <ftp://download.sourceforge.net/pub/sourceforge/e2fsprogs/e2fsprogs-1.19.tar.gz>
-o  <ftp://download.sourceforge.net/pub/sourceforge/e2fsprogs/e2fsprogs-1.19.src.rpm>
+o  <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.19.tar.gz>
+o  <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.19-0.src.rpm>
 
 Reiserfsprogs
 -------------
-o  <ftp://ftp.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.x.0d.tar.gz>
+o  <ftp://ftp.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.x.0j.tar.gz>
 
 LVM toolset
 -----------
@@ -347,7 +347,7 @@
 
 PPP
 ---
-o  <ftp://linuxcare.com.au/pub/ppp/ppp-2.4.0.tar.gz>
+o  <ftp://ftp.samba.org/ppp/ppp-2.4.0.tar.gz>
 
 Isdn4k-utils
 ------------
diff -u --recursive --new-file v2.4.3/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.4.3/linux/Documentation/Configure.help	Sun Mar 25 18:24:31 2001
+++ linux/Documentation/Configure.help	Fri Apr 20 16:23:12 2001
@@ -13,8 +13,10 @@
 #     http://www.traduc.org/kernelfr
 #   - Spanish, by Carlos Perelló Marín (fperllo@ehome.encis.es), at
 #     http://visar.csustan.edu/~carlos/
+#     XXX: Site has moved, new location has no Configure.help trans.
 #   - Italian, by Alessandro Rubini (rubini@linux.it), at
 #     ftp://ftp-pavia1.linux.it/pub/linux/Configure.help
+#     XXX: ftp-pavia1.linux.it: Non-existent host/domain
 #   - Polish, by Cezar Cichocki (cezar@cs.net.pl), at
 #     http://www.cs.net.pl/~cezar/Kernel
 #   - German, by SuSE, at http://www.suse.de/~ke/kernel . This patch
@@ -268,6 +270,11 @@
   Most normal users won't need the RAM disk functionality, and can
   thus say N here.
 
+Default RAM disk size
+CONFIG_BLK_DEV_RAM_SIZE
+  The default value is 4096. Only change this if you know what are
+  you doing. If you are using IBM S/390, then set this to 8192.
+
 Initial RAM disk (initrd) support
 CONFIG_BLK_DEV_INITRD
   The initial RAM disk is a RAM disk that is loaded by the boot loader
@@ -415,7 +422,7 @@
 
   To fine-tune ATA/IDE drive/interface parameters for improved
   performance, look for the hdparm package at
-  ftp://metalab.unc.edu/pub/Linux/kernel/patches/diskdrives/ .
+  http://www.ibiblio.org/pub/Linux/system/hardware .
 
   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),
@@ -711,7 +718,7 @@
 IGNORE word93 Validation BITS
 CONFIG_IDEDMA_IVB
   Since various rules were applied and created ... et al. as it relates
-  the detection of vaild cable signals.  This is a result of unclear terms
+  the detection of valid cable signals.  This is a result of unclear terms
   in ATA-4 and ATA-5 standards.
 
   It is normally safe to answer Y; however, the default is N.
@@ -1299,14 +1306,37 @@
   have a high-level driver for the type of device that you want to
   support.
 
-MicroSolutions backpack protocol
+Micro Solutions BACKPACK Series 5 protocol
 CONFIG_PARIDE_BPCK
-  This option enables support for the MicroSolutions backpack parallel
-  port IDE protocol. If you chose to build PARIDE support into your
-  kernel, you may answer Y here to build in the protocol driver,
-  otherwise you should answer M to build it as a loadable module. The
-  module will be called bpck.o. You must also have a high-level driver
-  for the type of device that you want to support.
+  This option enables support for the Micro Solutions BACKPACK parallel
+  port Series 5 IDE protocol. (Most BACKPACK drives made before 1999 were 
+  Series 5) Series 5 drives will NOT always have the Series noted on the
+  bottom of the drive. Series 6 drivers will. 
+
+  In other words, if your BACKPACK drive dosen't say "Series 6" on the
+  bottom, enable this option.
+
+  If you chose to build PARIDE support into your kernel, you may answer Y
+  here to build in the protocol driver, otherwise you should answer M to
+  build it as a loadable module. The module will be called bpck.o. You
+  must also have a high-level driver for the type of device that you want
+  to support.
+
+Micro Solutions BACKPACK Series 6 protocol
+CONFIG_PARIDE_BPCK6
+  This option enables support for the Micro Solutions BACKPACK parallel
+  port Series 6 IDE protocol. (Most BACKPACK drives made after 1999 were 
+  Series 6) Series 6 drives will have the Series noted on the bottom of
+  the drive. Series 5 drivers don't always have it noted. 
+
+  In other words, if your BACKPACK drive says "Series 6" on the bottom,
+  enable this option.
+
+  If you chose to build PARIDE support into your kernel, you may answer Y
+  here to build in the protocol driver, otherwise you should answer M to
+  build it as a loadable module. The module will be called bpck6.o. You
+  must also have a high-level driver for the type of device that you want
+  to support.
 
 DataStor Commuter protocol
 CONFIG_PARIDE_COMM
@@ -1587,6 +1617,27 @@
   This enables support for the VR5000-based NEC DDB Vrc-5074
   evaluation board.
 
+Support for NEC DDB Vrc-5476
+CONFIG_DDB5476
+  This enables support for the R5432-based NEC DDB Vrc-5476
+  evaluation board.
+
+  Features : kernel debugging, serial terminal, NFS root fs, on-board
+  ether port (with a patch to tulip driver), IDE controller, PS2 keyboard
+  PS2 mouse, etc.
+
+  TODO : USB, Compact-PCI interface.
+
+Support for MIPS Atlas board
+CONFIG_MIPS_ATLAS
+  This enables support for the QED R5231-based MIPS Atlas evaluation
+  board.
+
+Support for MIPS Malta board
+CONFIG_MIPS_MALTA
+  This enables support for the VR5000-based MIPS Malta evaluation
+  board.
+
 Support for Mips Magnum 4000
 CONFIG_MIPS_MAGNUM_4000
   This is a machine with a R4000 100 MHz CPU. To compile a Linux
@@ -1616,12 +1667,12 @@
 CONFIG_SGI_SN0_N_MODE
   The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be
   configured in either N-Modes which allows for more nodes or M-Mode
-  which allows for more more memory.  Your system is most probably
+  which allows for more memory.  Your system is most probably
   running in M-Mode, so you should say N here.
 
 MIPS JAZZ onboard SONIC Ethernet support
 CONFIG_MIPS_JAZZ_SONIC
-  This is the driver for the onboard card of of MIPS Magnum 4000,
+  This is the driver for the onboard card of MIPS Magnum 4000,
   Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
 
 MIPS JAZZ FAS216 SCSI support
@@ -1630,6 +1681,12 @@
   4000, Acer PICA, Olivetti M700-10 and a few other identical OEM
   systems.
 
+Kernel floating-point instruction emulation
+CONFIG_MIPS_FPU_EMULATOR
+  This option enables the MIPS software floatingpoint support.  Due to the
+  way floatingpoint works you should always enable this option unless
+  you exactly know what you're doing.
+
 PCMCIA SCSI adapter support
 CONFIG_SCSI_PCMCIA
   Say Y here if you intend to attach a PCMCIA or CardBus card to your
@@ -1726,6 +1783,10 @@
   certain types of data to get through the socket. Linux Socket
   Filtering works on all socket types except TCP for now. See the text
   file Documentation/networking/filter.txt for more information.
+
+  You need to say Y here if you want to use PPP packet filtering
+  (see the CONFIG_PPP_FILTER option below).
+
   If unsure, say N.
 
 Network packet filtering
@@ -2110,7 +2171,6 @@
   If you want to compile it as a module, say M here and read
   Documentation/modules.txt.  If unsure, say `N'.
 
-
 TCP Explicit Congestion Notification support
 CONFIG_INET_ECN
   Explicit Congestion Notification (ECN) allows routers to notify
@@ -2386,7 +2446,7 @@
   of those special I/O ports.
 
 SGI PROM Console Support
-CONFIG_SGI_PROM_CONSOLE
+CONFIG_ARC_CONSOLE
   Say Y here if you want to use the PROMs for console I/O.
 
 SGI Zilog85C30 serial support
@@ -2433,20 +2493,6 @@
   a module, say M here and read Documentation/modules.txt. If unsure,
   say N.
 
-CardBus serial device support
-CONFIG_PCMCIA_SERIAL_CB
-  Say Y here to enable support for CardBus serial devices, including
-  serial port cards, modems, and the modem functions of multi-function
-  ethernet/modem devices. (CardBus cards are the newer and better 
-  version of PCMCIA- or PC-cards: credit card size devices often 
-  used with laptops.)
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called serial_cb.o. If you want to compile it as
-  a module, say M here and read Documentation/modules.txt. If unsure,
-  say N.
-
 /dev/agpgart (AGP Support) (EXPERIMENTAL)
 CONFIG_AGP
   AGP (Accelerated Graphics Port) is a bus system mainly used to
@@ -2821,14 +2867,6 @@
   section 6.4 of the Linux Programmer's Guide, available from
   http://www.linuxdoc.org/docs.html#guide .
 
-  Shared memory is now implemented using a new (minimal) virtual file
-  system. To mount it automatically at system startup just add the
-  following line to your /etc/fstab:
-
-  none	/dev/shm	shm	defaults	0 0
-
-  Saying Y here enlarges your kernel by about 18 KB. Just say Y.
-
 BSD Process Accounting
 CONFIG_BSD_PROCESS_ACCT
   If you say Y here, a user level program will be able to instruct the
@@ -2994,14 +3032,16 @@
    - "Pentium-Classic" for the Intel Pentium.
    - "Pentium-MMX" for the Intel Pentium MMX.
    - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II.
-   - "Pentium-III" for the Intel Pentium III.
-   - "Pentium-4" for the Intel Pentium 4
+   - "Pentium-III" for the Intel Pentium III
+     and Celerons based on the coppermine core.
+   - "Pentium-4" for the Intel Pentium 4.
    - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D).
-   - "Athlon" for the AMD Athlon (K7).
+   - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird).
    - "Crusoe" for the Transmeta Crusoe series.
    - "Winchip-C6" for original IDT Winchip.
    - "Winchip-2" for IDT Winchip 2.
    - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
+   - "CyrixIII" for VIA Cyrix III or VIA C3.
 
   If you don't know what to do, choose "386".
 
@@ -3509,7 +3549,7 @@
 Virtual Frame Buffer support (ONLY FOR TESTING!)
 CONFIG_FB_VIRTUAL
   This is a `virtual' frame buffer device. It operates on a chunk of
-  unswapable kernel memory instead of on the memory of a graphics
+  unswappable kernel memory instead of on the memory of a graphics
   board. This means you cannot see any output sent to this frame
   buffer device, while it does consume precious memory. The main use
   of this frame buffer device is testing and debugging the frame
@@ -4301,7 +4341,7 @@
   packets with different FWMARK ("firewalling mark") values
   (see ipchains(8), "-m" argument).
 
-Appletalk interfaces support
+AppleTalk interfaces support
 CONFIG_APPLETALK
   AppleTalk is the way Apple computers speak to each other on a
   network. If your Linux box is connected to such a network and you
@@ -4314,11 +4354,10 @@
   want to join the conversation, say Y. You will need to use the
   netatalk package so that your Linux box can act as a print and file
   server for Macs as well as access AppleTalk printers. Check out
-  http://threepio.hitchcock.org/cgi-bin/faq/netatalk/faq.pl on the WWW
-  for details. EtherTalk is the name used for AppleTalk over Ethernet
-  and the cheaper and slower LocalTalk is AppleTalk over a proprietary
-  Apple network using serial links. EtherTalk and LocalTalk are fully
-  supported by Linux.
+  http://www.zettabyte.net/netatalk/ on the WWW for details. EtherTalk 
+  is the name used for AppleTalk over Ethernet and the cheaper and 
+  slower LocalTalk is AppleTalk over a proprietary Apple network using
+  serial links. EtherTalk and LocalTalk are fully supported by Linux.
 
   General information about how to connect Linux, Windows machines and
   Macs is on the WWW at http://www.eats.com/linux_mac_win.html . The
@@ -4329,8 +4368,10 @@
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module is called appletalk.o. If you want to compile it as a
-  module, say M here and read Documentation/modules.txt. I hear that
-  the GNU boycott of Apple is over, so even politically correct people
+  module, say M here and read Documentation/modules.txt.  You almost
+  certainly want to compile it as a module so you can restart your 
+  AppleTalk stack without rebooting your machine.  I hear that the 
+  GNU boycott of Apple is over, so even politically correct people
   are allowed to say Y here.
 
 AppleTalk-IP driver support
@@ -4831,7 +4872,7 @@
   with the Frames Diverter on, can do some *really* transparent www 
   caching using a Squid proxy for example.
 
-  This is very usefull when you don't want to change your router's
+  This is very useful when you don't want to change your router's
   config (or if you simply don't have access to it).
 
   The other possible usages of diverting Ethernet Frames are numberous:
@@ -4916,7 +4957,7 @@
 
 Routing messages
 CONFIG_RTNETLINK
-  If you say Y here, userspace programs can receive some network
+  If you say Y here, user space programs can receive some network
   related routing information over the netlink. 'rtmon', supplied
   with the iproute2 package (ftp://ftp.inr.ac.ru), can read and
   interpret this data.  Information sent to the kernel over this link
@@ -5084,6 +5125,15 @@
   Note that extended debugging may create certain race conditions
   itself. Enable this ONLY if you suspect problems with the driver.
 
+Fujitsu FireStream (FS50/FS155)
+CONFIG_ATM_FIRESTREAM
+  Driver for the Fujitsu FireStream 155 (MB86697) and 
+  FireStream 50 (MB86695) ATM PCI chips.
+
+  This driver is also available as a module. If you want to compile
+  it as a module, say M here and read Documentation/modules.txt. The
+  module will be called firestream.o.
+
 Enable usec resolution timestamps
 CONFIG_ATM_ZATM_EXACT_TS
   The uPD98401 SAR chip supports a high-resolution timer (approx. 30
@@ -7068,6 +7118,17 @@
 
   If unsure, say N.
 
+PPP filtering (EXPERIMENTAL)
+CONFIG_PPP_FILTER
+  Say Y here if you want to be able to filter the packets passing over
+  PPP interfaces.  This allows you to control which packets count as
+  activity (i.e. which packets will reset the idle timer or bring up
+  a demand-dialled link) and which packets are to be dropped entirely.
+  You need to say Y here if you wish to use the pass-filter and
+  active-filter options to pppd.
+
+  If unsure, say N.
+
 PPP support for async serial ports
 CONFIG_PPP_ASYNC
   Say Y (or M) here if you want to be able to use PPP over standard
@@ -8078,6 +8139,18 @@
   The module will be called cosa.o. For general information about
   modules read Documentation/modules.txt.
 
+Etinc PCISYNC serial boards support
+CONFIG_DSCC4
+  This is a driver for Etinc PCISYNC boards based on the Infineon
+  (ex. Siemens) DSCC4 chipset. It is supposed to work with the four
+  ports card. Take a look at http://www.cogenit.fr/dscc4
+  for further informations about the driver and his configuration.
+
+  The driver will be compiled as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called dscc4.o. For general information about
+  modules read Documentation/modules.txt.
+
 Lan Media sync serial boards support
 CONFIG_LANMEDIA
   This is a driver for the following Lan Media family of serial boards.
@@ -8164,13 +8237,26 @@
 
 Sangoma WANPIPE(tm) multiprotocol cards
 CONFIG_VENDOR_SANGOMA
-  WANPIPE from Sangoma Technologies Inc. (http://www.sangoma.com ) is
-  a family of intelligent multiprotocol WAN adapters with data
-  transfer rates up to T1 (1.544 Mbps). They are also known as
-  Synchronous Data Link Adapters (SDLA) and designated S502E(A), S503
-  or S508. These cards support the X.25, Frame Relay, and PPP
-  protocols. If you have one or more of these cards, say Y to this
-  option; you may then also want to read the file
+
+  WANPIPE from Sangoma Technologies Inc. (http://www.sangoma.com)
+  is a family of intelligent multiprotocol WAN adapters with data 
+  transfer rates up to 4Mbps. They are also known as Synchronous 
+  Data Link Adapters (SDLA) and are designated as S514-PCI or S508-ISA. 
+  These cards support
+  
+    - X.25, Frame Relay, PPP, Cisco HDLC protocols. 
+  
+    - API support for protocols like HDLC (LAPB), 
+      HDLC Streaming, X.25, Frame Relay and BiSync. 
+  
+    - Ethernet Bridging over Frame Relay protocol.
+
+    - MULTILINK PPP
+
+    - Async PPP (Modem Dialup)
+
+  If you have one or more of these cards, say M to this option; you
+  may then also want to read the file  
   Documentation/networking/wanpipe.txt. The next questions will ask
   you about the protocols you want the driver to support.
 
@@ -8179,44 +8265,58 @@
   The module will be called wanpipe.o. For general information about
   modules read Documentation/modules.txt.
 
-Maximum number of cards
-CONFIG_WANPIPE_CARDS
-  Enter number of WANPIPE adapters installed in your machine. The
-  driver can support up to 8 cards. You may enter more than you
-  actually have if you plan to add more cards in the future without
-  re-compiling the driver, but remember that in this case you'll waste
-  some kernel memory (about 1K per card).
-
-WANPIPE Cisco HDLC support
-CONFIG_WANPIPE_CHDLC
-  Say Y to this option if you are planning to connect a WANPIPE card
-  to a connection which uses the synchronous Cisco HDLC (High-level
-  Data Link Control) protocol. This protocol is often used on
-  high-speed leased lines like T1/E1.
-
 WANPIPE X.25 support
 CONFIG_WANPIPE_X25
   Say Y to this option if you are planning to connect a WANPIPE card
-  to an X.25 network. You should then also have said Y to "CCITT X.25
-  Packet Layer" and "LAPB Data Link Driver", above. If you say N, the
-  X.25 support will not be included in the driver (saves about 16 KB
-  of kernel memory).
+  to an X.25 network.  Note, this feature also includes the X.25 API
+  support used to develope custom applications over the X.25 protocol.
+  If you say N, the X.25 support will not be included in the driver. 
+  The X.25 option is supported on S514-PCI and S508-ISA cards.
 
 WANPIPE Frame Relay support
 CONFIG_WANPIPE_FR
   Say Y to this option if you are planning to connect a WANPIPE card
-  to a frame relay network. You should then also have said Y to "Frame
-  Relay (DLCI) support", above. If you say N, the frame relay
-  support will not be included in the driver (saves about 16 KB of
-  kernel memory).
+  to a frame relay network, or use frame relay API to develope 
+  custom applications over the Frame  Relay protocol.  
+  This feature also contains the Ethernet Bridging over Frame Relay,
+  where a WANPIPE frame relay link can be directly connected to the Linux
+  kernel bridge. If you say N, the frame relay support will
+  not be included in the driver. The Frame Relay option is 
+  supported on S514-PCI and S508-ISA cards.
 
 WANPIPE PPP support
 CONFIG_WANPIPE_PPP
   Say Y to this option if you are planning to connect a WANPIPE card
-  to a leased line using Point-to-Point protocol (PPP). You should
-  then also have said Y to "PPP (point-to-point) support", above. If
-  you say N, the PPP support will not be included in the driver (saves
-  about 16 KB of kernel memory).
+  to a leased line using Point-to-Point protocol (PPP). If you say N,
+  the PPP support will not be included in the driver. The PPP option
+  is supported on S514-PCI/S508-ISA cards.
+
+WANPIPE MultiPort PPP support
+CONFIG_WANPIPE_MULTPPP
+  Say Y to this option if you are planning to connect a WANPIPE card
+  to a leased line using Point-to-Point protocol (PPP). Note, the
+  MultiPort PPP uses the Linux Kernel SyncPPP protocol over the Sangoma
+  HDLC Streaming adapter.  In this case each Sangoma adapter port 
+  can support an independent PPP connection.  For example, a single
+  Quad-Port PCI adapter can support up to four independent 
+  PPP links. If you say N,the PPP support will not be included 
+  in the driver. The PPP option is supported on S514-PCI/S508-ISA cards.
+ 	
+WANPIPE Cisco HDLC support
+CONFIG_WANPIPE_CHDLC
+  Say Y to this option if you are planning to connect a WANPIPE card
+  to a leased line using the Cisco HDLC protocol. This now supports
+  Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards. 
+  This support also allows user to build applications using the 
+  HDLC streaming API. 
+  
+  CHDLC Streaming driver also supports MULTILINK PPP
+  support that can bind multiple WANPIPE T1 cards into
+  a single logical channel.
+  
+  If you say  N, the Cisco HDLC support and 
+  HDLC streaming API and MULTILINK PPP will not be 
+  included in the driver.
 
 MultiGate/COMX support
 CONFIG_COMX
@@ -8288,7 +8388,7 @@
   If you want to compile this as a module, say M and read
   Documentation/modules.txt. The module will be called
   i810-tco.o.
-  
+
 MultiGate Cisco-HDLC and synchronous PPP protocol support
 CONFIG_COMX_PROTO_PPP
   Cisco-HDLC and synchronous PPP protocol driver for all MultiGate
@@ -8351,6 +8451,49 @@
   If you say N, the X.25 support will not be included in the driver
   (saves about 11 KB of kernel memory).
 
+Generic HDLC driver
+CONFIG_HDLC
+  Say Y to this option if your Linux box contains a WAN card supported
+  by this driver and you are planning to connect the box to a WAN
+  ( = Wide Area Network). You will need supporting software from
+  http://hq.pm.waw.pl/hdlc/.
+  Generic HDLC driver currently supports raw HDLC, Cisco HDLC, Frame
+  Relay, synchronous Point-to-Point Protocol (PPP) and X.25.
+
+  If unsure, say N here.
+
+Synchronous Point-to-Point Protocol (PPP)
+CONFIG_HDLC_PPP
+  Say Y to this option if you want generic HDLC driver to support
+  PPP over WAN (Wide Area Network) connections.
+
+  If unsure, say N here.
+
+CCITT X.25 protocol
+CONFIG_HDLC_X25
+  Say Y to this option if you want generic HDLC driver to support
+  X.25 protocol over WAN (Wide Area Network) connections.
+
+  If unsure, say N here.
+
+SDL RISCom/N2 driver
+CONFIG_N2
+  This driver is for RISCom/N2 single or dual channel ISA cards
+  made by SDL Communications Inc. If you have such a card,
+  say Y here and see http://hq.pm.waw.pl/pub/hdlc/
+
+  Note that N2csu and N2dds cards are not supported by this driver.
+
+  If unsure, say N here.
+
+Moxa C101 driver
+CONFIG_C101
+  This driver is for C101 SuperSync ISA cards made by Moxa
+  Technologies Co., Ltd. If you have such a card,
+  say Y here and see http://hq.pm.waw.pl/pub/hdlc/
+
+  If unsure, say N here.
+
 Ethernet (10 or 100Mbit)
 CONFIG_NET_ETHERNET
   Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
@@ -10055,62 +10198,100 @@
 Memory Technology Device (MTD) support
 CONFIG_MTD
   Memory Technology Devices are flash, RAM and similar chips, often
-  used for solid state filesystems on embedded devices. This option
+  used for solid state file systems 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.
 
+MTD debugging support
+CONFIG_MTD_DEBUG
+  This turns on low-level debugging for the entire MTD sub-system.
+
+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 support
+M-Systems Disk-On-Chip 2000 and Millennium support
 CONFIG_MTD_DOC2000
   This provides an MTD device driver for the M-Systems DiskOnChip
-  2000 devices. If you use this, you probably also want the NFTL
-  'NAND Flash Translation Layer' below, which is used to emulate
+  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.
+
+  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.
 
-M-Systems Disk-On-Chip Millennium support
+Alternative Disk-On-Chip Millennium support
 CONFIG_MTD_DOC2001
-  This provides an MTD device driver for the M-Systems DiskOnChip
-  Millennium devices. If you use this, you probably also want the
-  NFTL 'NAND Flash Translation Layer' below, which is used to emulate
+  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
+
+  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.
 
+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.
+
 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.
 
-Ramix PMC551 PCI Mezzanine ram card support
-CONFIG_MTD_PMC551
-  This provides an MTD device driver for the Ramix PMC551 RAM card.
-  If you have one, you probably want to enable this.
-
-PMC551 256M DRAM Bugfix.
+PMC551 256M DRAM Bugfix
 CONFIG_MTD_PMC551_BUGFIX
-  Some PMC551 boards hacve invalid column and row mux values. This 
-  option will fix them, but will break other memory configurations.
+  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 useful if you are developing on this driver or suspect a
+  possible hardware or driver bug.  If unsure say N.
 
 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, or unless you want to use it in place of a ramdisk
-  when I've eventually got round to making the CONFIG_BLK_DEV option
-  and you've turned it off.
+  This enables a test MTD device driver which uses vmalloc() to
+  provide storage. You probably want to say 'N' unless you're
+  testing stuff.
 
 Common Flash Interface (CFI) support
 CONFIG_MTD_CFI
-  Intel's Common Flash Interface specification provides a universal
-  method for probing the capabilities of flash devices. If you wish
-  to support any device which uses CFI-compliant devices, you need
-  to enable this option.
+  The Common Flash Interface specification was developed by Intel,
+  AMD and other flash manufactures that provides a universal method
+  for probing the capabilities of flash devices. If you wish to
+  support any device that is CFI-compliant, you need to enable this
+  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
 CONFIG_MTD_CFI_INTELEXT
@@ -10122,10 +10303,10 @@
 Flash chip mapping in physical memory
 CONFIG_MTD_PHYSMAP
   This provides a 'mapping' driver which allows the CFI probe and
-  command set driver code to communicate with flash chips which 
+  command set driver code to communicate with flash chips which
   are mapped physically into the CPU's memory. You will need to
   configure the physical address and size of the flash chips on
-  your particular board.
+  your particular board as well as the bus width.
 
 Physical start location of flash chip mapping
 CONFIG_MTD_PHYSMAP_START
@@ -10143,38 +10324,51 @@
   map which should hopefully be in the documentation for your
   board. 
 
+CONFIG_MTD_PHYSMAP_BUSWIDTH
+  This is the total width of the data bus of the flash devices
+  in octets. For example, if you have a data bus width of 32
+  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 
+  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.
+  you probably want to enable this mapping driver. More info is at
+  (http://www.itc.hu/).
 
 Flash chip mapping on Nora
 CONFIG_MTD_NORA
   If you had to ask, you don't have one. Say 'N'.
 
+Flash chip mapping on PNC2000
+CONFIG_MTD_PNC2000
+  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. You will also need to complete and enable the driver
-  for JEDEC flash chips.
+  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 
+  The RPXLite PowerPC board has CFI-compliant chips mapped in
   a strange sparse mapping. This 'mapping' driver supports that
   arrangement, allowing the CFI probe and command set driver code
-  to communicate with the chips on the RPXLite board.
+  to communicate with the chips on the RPXLite board. More at
+  (http://www.embeddedplanet.com/rpx_lite_specification_sheet.htm).
 
 Flash chip mapping on Tempustech VMAX SBC301
 CONFIG_MTD_VMAX
   This provides a 'mapping' driver which supports the way in which
   the flash chips are connected in the Tempustech VMAX SBC301 Single
-  Board Computer. You will also need to complete and enable the driver
-  for JEDEC flash chips.
+  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
@@ -10195,15 +10389,15 @@
 
   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
+  this is very unsafe, but could be useful for file systems which are
   almost never written to.
 
 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. You may find
+  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 
@@ -10214,8 +10408,8 @@
 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. You may find
+  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 
@@ -10224,8 +10418,8 @@
 
 Write support for NFTL (EXPERIMENTAL)
 CONFIG_NFTL_RW
-  If you're lucky, this will actually work. Don't whinge if it doesn't.
-  Contact dwmw2@infradead.org if you want to help to make it more 
+  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.
 
 Support for USB
@@ -10399,6 +10593,16 @@
 
   If unsure, say Y.
 
+Input core support
+CONFIG_INPUT
+  Say Y here if you want to enable any of the following options for
+  USB Human Interface Device (HID) support.
+
+  Say Y here if you want to enable any of the USB HID options in the
+  USB support section which require Input core support.
+
+  Otherwise, say N.
+
 Keyboard support
 CONFIG_INPUT_KEYBDEV
   Say Y here if you want your USB HID keyboard (or an ADB keyboard
@@ -10826,16 +11030,16 @@
 USB device file system
 CONFIG_USB_DEVICEFS
   If you say Y here (and to "/proc file system support" below), you
-  will get a file /proc/usb/devices which lists the devices currently
-  connected to your USB busses, a file /proc/usb/drivers which lists
-  the USB kernel client drivers currently loaded, and for every
-  connected device a file named "/proc/usb/xxx/yyy", where xxx is the
-  bus number and yyy the device number; the latter files can be used
-  by user space programs to talk directly to the device. These files
-  are "virtual", meaning they are generated on the fly and not stored
-  on the hard drive.
+  will get a file /proc/bus/usb/devices which lists the devices
+  currently connected to your USB busses, a file /proc/bus/usb/drivers
+  which lists the USB kernel client drivers currently loaded, and for
+  every connected device a file named "/proc/bus/usb/xxx/yyy", where
+  xxx is the bus number and yyy the device number; the latter files
+  can be used by user space programs to talk directly to the device.
+  These files are "virtual", meaning they are generated on the fly
+  and not stored on the hard drive.
   
-  For the format of the /proc/usb/ files, please read
+  For the format of the /proc/bus/usb/ files, please read
   Documentation/usb/proc_usb_info.txt. 
 
   Please note that this code is completely unrelated to devfs, the
@@ -11072,23 +11276,44 @@
 
   If unsure, say N.
    
+Virtual memory file system support
+CONFIG_TMPFS
+  Tmpfs is a file system which keeps all files in virtual memory.
+
+  In contrast to RAM disks, which get allocated a fixed amount of
+  physical RAM, tmpfs grows and shrinks to accommodate the files it
+  contains and is able to swap unneeded pages out to swap space.
+
+  Everything is "virtual" in the sense that no files will be created
+  on your hard drive; if you reboot, everything in tmpfs will be
+  lost.
+  
+  You should mount the filesystem somewhere to be able to use
+  POSIX shared memory. Adding the following line to /etc/fstab should
+  take care of things:
+
+  tmpfs		/dev/shm	tmpfs		defaults	0 0
+
+  Remember to create the directory that you intend to mount tmpfs on
+  if necessary (/dev/shm is automagically created if you use devfs).
+
+  You can set limits for the number of blocks and inodes used by the
+  filesystem with the mount options "size", "nr_blocks" and
+  "nr_inodes". These parameters accept a suffix k, m or g for kilo,
+  mega and giga and can be changed on remount.
+  
+  The initial permissions of the root directory can be set with the
+  mount option "mode".
+
 Simple RAM-based file system support
 CONFIG_RAMFS
   Ramfs is a file system which keeps all files in RAM. It allows
   read and write access.
 
-  In contrast to RAM disks, which get allocated a fixed amount of RAM,
-  ramfs grows and shrinks to accommodate the files it contains.
+  It is more of an programming example than a useable filesystem. If
+  you need a file system which lives in RAM with limit checking use
+  tmpfs.
 
-  Before you can use this RAM-based file system, it has to be mounted,
-  meaning it has to be given a location in the directory hierarchy. If
-  you want to use the location /ramfiles for example, you would have
-  to create that directory first and then mount the file system by
-  saying "mount -t ramfs ramfs /ramfiles" or the equivalent line in
-  /etc/fstab. Everything is "virtual" in the sense that no files will
-  be created on your hard drive; if you reboot, everything in
-  /ramfiles will be lost.
-  
   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
@@ -11634,21 +11859,16 @@
   whenever you want), say M here and read Documentation/modules.txt.
   The module will be called efs.o. 
 
-Journalling Flash File System (JFFS) support (EXPERIMENTAL)
+Support for the Journalling Flash Filesystem
 CONFIG_JFFS_FS
-  JFFS is a new file system designed for use on flash memory devices
-  rather than on block devices. It was developed on the 2.0 kernel
-  by Axis Communications AB for use on their Linux-based products,
-  and released under GPL, then 'borrowed' and ported to work with 
-  the 2.4 kernel and the new Memory Technology Device system. 
-
-  The 2.4 port is experimental and not yet supported by Axis. Basically,
-  the good bits are probably theirs, and if it's broken in 2.4 it's 
-  probably our fault. See http://www.developer.axis.com/software/jffs/
-  for more information about JFFS.
-
-  Any potential patches or queries should be sent to Axis' mailing 
-  list for JFFS: <jffs-dev@axis.com>
+  JFFS is the Journaling Flash File System developed by Axis
+  Communications in Sweden, aimed at providing a crash/powerdown-safe
+  filesystem for disk-less embedded devices. Further information is
+  available at (http://developer.axis.com/software/jffs/).
+
+JFFS debugging verbosity
+CONFIG_JFFS_FS_VERBOSE
+  Determines the verbosity level of the JFFS debugging messages.
 
 UFS file system support (read-only)
 CONFIG_UFS_FS
@@ -11723,6 +11943,12 @@
   file system support", above. If you don't know what all this is
   about, say N.
 
+Minix subpartition support
+CONFIG_MINIX_SUBPARTITION
+  Minix 2.0.0/2.0.2 subpartition table support for Linux.
+  Say Y here if you want to mount and use Minix 2.0.0/2.0.2
+  subpartitions.
+
 Sun partition tables support
 CONFIG_SUN_PARTITION
   Like most systems, SunOS uses its own hard disk partition table
@@ -11749,6 +11975,12 @@
   Say Y here if you would like to be able to read the hard disk
   partition table format used by SGI machines.
 
+Ultrix partition support
+CONFIG_ULTRIX_PARTITION
+  Say Y here if you would like to be able to read the hard disk
+  partition table format used by DEC (now Compaq) Ultrix machines.
+  Otherwise, say N.
+
 ADFS file system support (EXPERIMENTAL)
 CONFIG_ADFS_FS
   The Acorn Disc Filing System is the standard file system of the
@@ -11998,7 +12230,7 @@
 
 nls default codepage
 CONFIG_NLS_DEFAULT
-  The default NLS used when mounting filesystem. Currently, the valid
+  The default NLS used when mounting file system. Currently, the valid
   values are:
   big5, cp437, cp737, cp775, cp850, cp852, cp855, cp857, cp860, cp861,
   cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp932, cp936,
@@ -12187,7 +12419,7 @@
 
 nls codepage 932
 CONFIG_NLS_CODEPAGE_932
-  The Microsoft fat filesystem family can deal with filenames in
+  The Microsoft FAT file system family can deal with filenames in
   native language character sets. These character sets are stored in
   so-called DOS codepages. You need to include the appropriate
   codepage if you want to be able to read/write these filenames on
@@ -12199,7 +12431,7 @@
 
 nls codepage 936
 CONFIG_NLS_CODEPAGE_936
-  The Microsoft fat filesystem family can deal with filenames in
+  The Microsoft FAT file system family can deal with filenames in
   native language character sets. These character sets are stored in
   so-called DOS codepages. You need to include the appropriate
   codepage if you want to be able to read/write these filenames on
@@ -12210,7 +12442,7 @@
 
 nls codepage 949
 CONFIG_NLS_CODEPAGE_949
-  The Microsoft fat filesystem family can deal with filenames in
+  The Microsoft FAT file system family can deal with filenames in
   native language character sets. These character sets are stored in
   so-called DOS codepages. You need to include the appropriate
   codepage if you want to be able to read/write these filenames on
@@ -12220,7 +12452,7 @@
 
 nls codepage 950
 CONFIG_NLS_CODEPAGE_950
-  The Microsoft fat filesystem family can deal with filenames in
+  The Microsoft FAT file system family can deal with filenames in
   native language character sets. These character sets are stored in
   so-called DOS codepages. You need to include the appropriate
   codepage if you want to be able to read/write these filenames on
@@ -12736,8 +12968,8 @@
   how to pass options to the kernel at boot time.) The syntax of the
   "lp" command line option can be found in drivers/char/lp.c.
 
-  If you have more than 3 printers, you need to increase the LP_NO
-  variable in lp.c.
+  If you have more than 8 printers, you need to increase the LP_NO
+  macro in lp.c and the PARPORT_MAX macro in parport.h.
 
 Support for console on line printer
 CONFIG_LP_CONSOLE
@@ -13742,17 +13974,32 @@
   module, say M here and read Documentation/modules.txt. Most people
   will say N.
 
+ZF MachZ Watchdog
+CONFIG_MACHZ_WDT
+  If you are using a ZF Micro MachZ processor, say Y here, otherwise N.
+  This is the driver for the watchdog timer builtin on that processor
+  using ZF-Logic interface. This watchdog simply watches your kernel to
+  make sure it doesn't freeze, and if it does, it reboots your computer
+  after a certain amount of time.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module is called machzwd.o. If you want to compile it as a module,
+  say M here and read Documentation/modules.txt.
+
 Toshiba Laptop support
 CONFIG_TOSHIBA
-  If you intend to run this the kernel on a Toshiba portable say yes
-  here. This adds a driver to safely access the System Management
-  Mode of the CPU on Toshiba portables. The System Management Mode
+  This adds a driver to safely access the System Management Mode
+  of the CPU on Toshiba portables. The System Management Mode
   is used to set the BIOS and power saving options on Toshiba portables.
 
   For information on utilities to make use of this driver see the
-  Toshiba Linux utilities website at:
+  Toshiba Linux utilities web site at:
   http://www.buzzard.org.uk/toshiba/
 
+  Say Y if you intend to run this kernel on a Toshiba portable.
+  Say N otherwise.
+
 /dev/cpu/microcode - Intel IA32 CPU microcode support
 CONFIG_MICROCODE
   If you say Y here and also to "/dev file system support" in the
@@ -13787,6 +14034,18 @@
   with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
   /dev/cpu/31/cpuid.
 
+SBC-60XX Watchdog Timer
+CONFIG_60XX_WDT
+ This driver can be used with the watchdog timer found on some
+ single board computers, namely the 6010 PII based computer.
+ It may well work with other cards.  It reads port 0x443 to enable
+ and re-set the watchdog timer, and reads port 0x45 to disable
+ the watchdog.  If you have a card that behave in similar ways,
+ you can probably make this driver work with your card as well.
+
+ You can compile this driver directly into the kernel, or use
+ it as a module.  The module will be called sbc60xxwdt.o.
+
 Enhanced Real Time Clock Support
 CONFIG_RTC
   If you say Y here and create a character special file /dev/rtc with
@@ -14253,6 +14512,8 @@
   16 or Logitech SoundMan 16 sound card. Answer N if you have some
   other card made by Media Vision or Logitech since those are not
   PAS16 compatible. Please read Documentation/sound/PAS16.
+  It is not necessary to add Sound Blaster support separately; it
+  is included in PAS support.
 
   If you compile the driver into the kernel, you have to add
   "pas2=<io>,<irq>,<dma>,<dma2>,<sbio>,<sbirq>,<sbdma>,<sbdma2>
@@ -14459,13 +14720,15 @@
   See Documentation/sound/CS4232 for more information on configuring
   this card.
 
-Support for Yamaha OPL3-SA2, SA3, and SAx based PnP cards
+Support for Yamaha OPL3-SA2 and SA3 based PnP cards
 CONFIG_SOUND_OPL3SA2
   Say Y or M if you have a card based on one of these Yamaha
-  sound chipsets. Read Documentation/sound/OPL3-SA2 for more
-  information on configuring these cards.
+  sound chipsets or the "SAx", which is actually a SA3. Read
+  Documentation/sound/OPL3-SA2 for more information on configuring
+  these cards.
 
-  If you compile the driver into the kernel, you have to add
+  If you compile the driver into the kernel and do not also
+  configure in the optional ISA PnP support, you will have to add
   "opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>" to the kernel
   command line.
 
@@ -14647,7 +14910,7 @@
 
 SC-6600 CDROM Interface
 CONFIG_SC6600_CDROM
-  This is used to activate the the CDROM interface of the Audio Excel
+  This is used to activate the CDROM interface of the Audio Excel
   DSP 16 card. Enter: 0 for Sony, 1 for Panasonic, 2 for IDE, 4 for no
   CDROM present.
 
@@ -14661,6 +14924,11 @@
   driver as a module you have to specify the MPU I/O base address with
   the parameter 'mpu_base=0xNNN'.
 
+C-Media PCI (CMI8338/8378)
+CONFIG_SOUND_CMPCI
+  Say Y or M if you have a PCI sound card using the CMI8338
+  or the CMI8378 chip.set.
+
 Creative EMU10K1 based PCI sound cards
 CONFIG_SOUND_EMU10K1
   Say Y or M if you have a PCI sound card using the EMU10K1
@@ -15289,10 +15557,10 @@
   Enable support for the AVM T1 T1B card.
   Note: This is a PRI card and handle 30 B-channels.
 
-AVM C4 support
+AVM C4/C2 support
 CONFIG_ISDN_DRV_AVMB1_C4
-  Enable support for the AVM C4 PCI card.
-  This card handle 4 BRI ISDN lines (8 channels).
+  Enable support for the AVM C4/C2 PCI cards.
+  These cards handle 4/2 BRI ISDN lines (8/4 channels).
 
 Verbose reason code reporting (kernel size +=7K)
 CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
@@ -16523,6 +16791,68 @@
   from the running kernel whenever you want). If you want to compile
   it as a module, say M here and read Documentation/modules.txt.
 
+IBM's S/390 architecture
+CONFIG_ARCH_S390
+  Select this option, if you want to run the Kernel on one of IBM's
+  mainframes of the S/390 generation. You should have installed the
+  s390-compiler released by IBM (based on gcc-2.95.1) before.
+
+Merge some code into the kernel to make the image IPLable
+CONFIG_IPLABLE
+  If you want to use the produced kernel to IPL directly from a
+  device, you have to merge a bootsector specific to the device
+  into the first bytes of the kernel. You will have to select the
+  IPL device on another question, that pops up, when you select
+  CONFIG_IPLABE.
+
+IPL from a /390 tape unit
+CONFIG_IPL_TAPE
+  Select this option if you want to IPL the image from a Tape.
+
+IPL from a virtual card reader emulated by VM/ESA
+CONFIG_IPL_RDR_VM
+  Select this option if you are running under VM/ESA and want 
+  to IPL the image from the emulated card reader.
+
+IPL from a real card reader
+CONFIG_IPL_RDR
+  Select this option if you want to IPL the image from a real
+  card reader. Maybe you still got one and want to try. We didn't
+  test.
+
+IBMs S/390 Harddisks (DASDs)
+CONFIG_DASD
+  Enable this option if you want to access DASDs directly utilizing
+  S/390s channel subsystem commands. This is necessary for running
+  natively on a single image or an LPAR.
+
+Enable DASD fast write
+CONFIG_DASD_FAST_IO
+  Enable fast I/O for DASDs. That means that the next I/O command
+  is already issued at interrupt time, if an I/O request is pending.
+  This option gives significant speedup of I/O, because we don't
+  schedule the bottom-halves as often as Intel.
+
+Support for IBM-style disk-labels (S/390)
+CONFIG_S390_PARTITION
+  Enable this option to assure standard IBM labels on the DASDs.
+  You must enable it, if you are planning to access DASDs also
+  attached to another IBM mainframe operation system (OS/390, 
+  VM/ESA, VSE/ESA).
+
+ECKD devices
+CONFIG_DASD_ECKD
+  ECKD devices are the most commonly used devices. you should enable
+  this option unless you are very sure to have no ECKD device.
+
+CKD devices
+CONFIG_DASD_CKD
+  CKD devices are currently unsupported.
+
+FBA devices
+CONFIG_DASD_FBA
+  FBA devices are currently unsupported.
+
 SAB3036 tuner support
 CONFIG_TUNER_3036
   Say Y here to include support for Philips SAB3036 compatible tuners.
@@ -16559,7 +16889,7 @@
   Saying N will reduce the size of the Footbridge kernel.
 
 Include support for the EBSA285
-CONFIG_ARCH_EBSA285
+CONFIG_ARCH_EBSA285_HOST
   Say Y here if you intend to run this kernel on the EBSA285 card
   in host ("central function") mode.
 
@@ -16645,50 +16975,14 @@
   http://www.visuaide.com/pagevictor.en.html for information on
   this system.
 
-Support ARM610 processor
-CONFIG_CPU_ARM6
-  Say Y here if you wish to include support for the ARM610 processor.
-
-Support ARM710 processor
-CONFIG_CPU_ARM7
-  Say Y here if you wish to include support for the ARM710 processor.
-
-Support StrongARM(R) SA-110 processor
-CONFIG_CPU_SA110
-  Say Y here if you wish to include support for the Intel(R)
-  StrongARM(R) SA-110 processor.
-
-Support ARM720 processor
-CONFIG_CPU_ARM720
-  Say Y here if you wish to include support for the ARM720 processor.
-
-Support ARM920
-CONFIG_CPU_ARM920
-  Say Y here if you wish to include support for the ARM920 processor.
-
-Support ARM610 processor
-CONFIG_CPU_ARM6
-  Say Y here if you wish to include support for the ARM610 processor.
-
-Support ARM710 processor
-CONFIG_CPU_ARM7
-  Say Y here if you wish to include support for the ARM710 processor.
-
-Support StrongARM(R) SA-110 processor
-CONFIG_CPU_SA110
-  Say Y here if you wish to include support for the Intel(R)
-  StrongARM(R) SA-110 processor.
-
-Support ARM720 processor
-CONFIG_CPU_ARM720
-  Say Y here if you wish to include support for the ARM720 processor.
-
-Support ARM920
-CONFIG_CPU_ARM920
-  Say Y here if you wish to include support for the ARM920 processor.
+Load kernel using Angel Debug Monitor
+CONFIG_ANGELBOOT
+  Say Y if you plan to load the kernel using Angel, ARM Ltd's target
+  debug stub.  If you are not using Angel, you must say N.  It is
+  important to get this setting correct.
 
 Math emulation
-CONFIG_NWFPE
+CONFIG_FPE_NWFPE
   Say Y to include the NWFPE floating point emulator in the kernel.
   This is necessary to run most binaries. Linux does not currently
   support floating point hardware so you need to say Y here even if
@@ -16702,6 +16996,23 @@
   You may say N here if you are going to load the Acorn FPEmulator
   early in the bootup.
 
+CONFIG_FPE_FASTFPE
+  Say Y here to include the FAST floating point emulator in the kernel.
+  This is an experimental much faster emulator which has only 32 bit
+  precision for the mantissa. It does not support any exceptions. This
+  makes it very simple, it is approximately 4-8 times faster than NWFPE.
+
+  It should be sufficient for most programs. It is definitely not
+  suitable if you do scientific calculations that need double precision
+  for iteration formulas that sum up lots of very small numbers. If you
+  do not feel you need a faster FP emulation you should better choose
+  NWFPE.
+
+  It is also possible to say M to build the emulator as a module
+  (fastfpe.o). But keep in mind that you should only load the FP emulator
+  early in the bootup. You should never change from NWFPE to FASTFPE or
+  vice versa in an active system!
+
 DS1620 Thermometer support
 CONFIG_DS1620
   Say Y here to include support for the thermal management hardware
@@ -16721,11 +17032,12 @@
   you are concerned with the code size or don't want to see these
   messages.
 
-Compile kernel with frame pointer
-CONFIG_FRAME_POINTER
-  If you say Y here, the resulting kernel will be slightly larger and
-  slower, but it will give useful debugging information. If you don't
-  debug the kernel, you can say N.
+Compile kernel without frame pointer
+CONFIG_NO_FRAME_POINTER
+  If you say Y here, the resulting kernel will be slightly smaller and
+  faster. However, when a problem occurs with the kernel, the
+  information that is reported is severely limited. Most people
+  should say N here.
 
 User fault debugging
 CONFIG_DEBUG_USER
@@ -16833,6 +17145,21 @@
   you can make the first serial port the console by answering Y to
   this option.
 
+L7200 SDB keyboard support
+CONFIG_KEYBOARD_L7200
+  Enable this option if you would like to be able to use a keyboard
+  on a LinkUp Systems L7200 board.
+
+L7200 SDB Fujitsu keyboard support
+CONFIG_KEYBOARD_L7200_NORM
+  Select the Fujitsu keyboard if you want a normal QWERTY style
+  keyboard on the LinkUp SDB.
+
+L7200 SDB Prototype keyboard support
+CONFIG_KEYBOARD_L7200_DEMO
+  Select the prototype keyboard if you want to play with the
+  LCD/keyboard combination on the LinkUp SDB.
+
 Footbridge Mode
 CONFIG_HOST_FOOTBRIDGE
   The 21285 Footbridge chip can operate in either `host mode' or
@@ -16903,8 +17230,7 @@
   infrared communication and is supported by most laptops and PDA's.
 
   To use Linux support for the IrDA (tm) protocols, you will also need
-  some user-space utilities like the irmanager and probably irattach
-  as well. For more information, see the file
+  some user-space utilities like irattach. For more information, see the file
   Documentation/networking/irda.txt. You also want to read the
   IR-HOWTO, available at http://www.linuxdoc.org/docs.html#howto .
 
@@ -16912,6 +17238,10 @@
   want to compile it as a module, say M here and read
   Documentation/modules.txt.
 
+IrDA protocol options
+CONFIG_IRDA_OPTIONS
+  Say Y here if you want to configure any of the following IrDA options.
+
 IrDA Cache last LSAP
 CONFIG_IRDA_CACHE_LAST_LSAP
   Say Y here if you want IrLMP to cache the last LSAP used. This makes
@@ -16976,6 +17306,17 @@
   to another Linux machine running the IrLAN protocol for ad-hoc 
   networking!
 
+IrNET Protocol 
+CONFIG_IRNET
+  Say Y here if you want to build support for the IrNET protocol. If
+  you want to compile it as a module (irnet.o), say M here and read
+  Documentation/modules.txt. IrNET is a PPP driver, so you will also
+  need a working PPP subsystem (driver, daemon and config)...
+
+  IrNET is an alternate way to tranfer TCP/IP traffic over IrDA. It
+  uses synchronous PPP over a set of point to point IrDA sockets. You
+  can use it between Linux machine or with W2k.
+
 IrCOMM Protocol
 CONFIG_IRCOMM
   Say Y here if you want to build support for the IrCOMM protocol. If
@@ -17350,7 +17691,7 @@
 # LocalWords:  howto multicasting MULTICAST MBONE firewalling ipfw ACCT resp ip
 # LocalWords:  proc acct IPIP encapsulator decapsulator klogd PCTCP RARP EXT PS
 # LocalWords:  telnetting subnetted NAGLE rlogin NOSR ttyS TGA techinfo mbone nl
-# LocalWords:  Mb SKB IPX Novell dosemu Appletalk DDP ATALK vmalloc visar ehome
+# LocalWords:  Mb SKB IPX Novell dosemu DDP ATALK vmalloc visar ehome
 # LocalWords:  SD CHR scsi thingy SG CD LUNs LUN jukebox Adaptec BusLogic EATA
 # LocalWords:  buslogic DMA DPT ATT eata dma PIO UltraStor fdomain umsdos ext
 # LocalWords:  QLOGIC qlogic TMC seagate Trantor ultrastor FASST wd NETDEVICES
@@ -17378,7 +17719,7 @@
 # LocalWords:  Brumby pci TNC cis ohio faq usenet NETLINK dev hydra ca Tyne mem
 # LocalWords:  carleton DECstation SUNFD JENSEN Noname XXXM SLiRP LILO's amifb
 # LocalWords:  pppd Zilog ZS SRM bootloader ez mainmenu rarp ipfwadm paride pcd
-# LocalWords:  RTNETLINK mknod xos MTU lwared Macs mac netatalk macs cs Wolff
+# LocalWords:  RTNETLINK mknod xos MTU lwared Macs netatalk macs cs Wolff
 # LocalWords:  dartmouth flowerpt MultiMaster FlashPoint tudelft etherexpress
 # LocalWords:  ICL EtherTeam ETH IDESCSI TXC SmartRAID SmartCache httpd sjc dlp
 # LocalWords:  thesphere TwoServers BOOTP DHCP ncpfs BPQETHER BPQ MG HIPPI cern
@@ -17395,7 +17736,7 @@
 # LocalWords:  Keepalive linefill RELCOM keepalive analogue CDR conf CDI INIT
 # LocalWords:  OPTi isp irq noisp VFAT vfat NTFS losetup dmsdosfs dosfs ISDN MP
 # LocalWords:  NOWAYOUT behaviour dialin isdn callback BTX Teles  XXXX LVM lvm
-ICN EDSS Cisco
+# LocalWords:  ICN EDSS Cisco
 # LocalWords:  ipppd syncppp RFC MPP VJ downloaded icn NICCY Creatix shmem ufr
 # LocalWords:  ibp md ARCnet ether encap NDIS arcether ODI Amigas AmiTCP NetBSD
 # LocalWords:  initrd tue util DES funet des OnNet BIOSP smc Travan Iomega CMS
@@ -17522,7 +17863,7 @@
 # LocalWords:  AudioPCI lspci SonicVibes sonicvibes SPARCs roadrunner CLgen UPA
 # LocalWords:  swansea shtml Zoltrix zoltrix BINUTILS EGCS binutils VIDC DACs
 # LocalWords:  CyberVision Cirrus PowerBooks Topcat SBUS CGsix TurboGX BWtwo SS
-# LocalWords:  CGthree TCX unswapable vfb fbcon hicolor truecolor AFB ILBM SOC
+# LocalWords:  CGthree TCX unswappable vfb fbcon hicolor truecolor AFB ILBM SOC
 # LocalWords:  IPLAN gracilis Fibre SBus SparcSTORAGE SV jnewbigin swin QNX qnx
 # LocalWords:  PTY PTYS ptyxx ttyxx PTYs ssh sb Avance ALS pss pvv kerneli hd
 # LocalWords:  synth WaveFront MSND NONPNP AudioExcelDSP STRAM APUS CHRP MBX Nx
diff -u --recursive --new-file v2.4.3/linux/Documentation/DMA-mapping.txt linux/Documentation/DMA-mapping.txt
--- v2.4.3/linux/Documentation/DMA-mapping.txt	Tue Mar  6 22:44:15 2001
+++ linux/Documentation/DMA-mapping.txt	Thu Apr 19 08:38:48 2001
@@ -32,6 +32,35 @@
 the dma_addr_t type which should be used everywhere you hold a DMA
 (bus) address returned from the DMA mapping functions.
 
+			 What memory is DMA'able?
+
+The first piece of information you must know is what kernel memory can
+be used with the DMA mapping facilitites.  There has been an unwritten
+set of rules regarding this, and this text is an attempt to finally
+write them down.
+
+If you acquired your memory via the page allocator
+(i.e. __get_free_page*()) or the generic memory allocators
+(i.e. kmalloc() or kmem_cache_alloc()) then you may DMA to/from
+that memory using the addresses returned from those routines.
+
+This means specifically that you may _not_ use the memory/addresses
+returned from vmalloc() for DMA.  It is possible to DMA to the
+_underlying_ memory mapped into a vmalloc() area, but this requires
+walking page tables to get the physical addresses, and then
+translating each of those pages back to a kernel address using
+something like __va().
+
+This rule also means that you may not use kernel image addresses
+(ie. items in the kernel's data/text/bss segment, or your driver's)
+nor may you use kernel stack addresses for DMA.  Both of these items
+might be mapped somewhere entirely different than the rest of physical
+memory.
+
+What about block I/O and networking buffers?  The block I/O and
+networking subsystems make sure that the buffers they use are valid
+for you to DMA from/to.
+
 			DMA addressing limitations
 
 Does your device have any DMA addressing limitations?  For example, is
@@ -168,16 +197,21 @@
   optimizations the hardware allows.  To this end, when using
   such mappings you must be explicit about what you want to happen.
 
+Neither type of DMA mapping has alignment restrictions that come
+from PCI, although some devices may have such restrictions.
+
 		 Using Consistent DMA mappings.
 
-To allocate and map a consistent DMA region, you should do:
+To allocate and map large (PAGE_SIZE or so) consistent DMA regions,
+you should do:
 
 	dma_addr_t dma_handle;
 
 	cpu_addr = pci_alloc_consistent(dev, size, &dma_handle);
 
 where dev is a struct pci_dev *. You should pass NULL for PCI like buses
-where devices don't have struct pci_dev (like ISA, EISA).
+where devices don't have struct pci_dev (like ISA, EISA).  This may be
+called in interrupt context. 
 
 This argument is needed because the DMA translations may be bus
 specific (and often is private to the bus which the device is attached
@@ -186,7 +220,9 @@
 Size is the length of the region you want to allocate.
 
 This routine will allocate RAM for that region, so it acts similarly to
-__get_free_pages (but takes size instead of a page order).
+__get_free_pages (but takes size instead of a page order).  If your
+driver needs regions sized smaller than a page, you may prefer using
+the pci_pool interface, described below.
 
 It returns two values: the virtual address which you can use to access
 it from the CPU and dma_handle which you pass to the card.
@@ -205,6 +241,51 @@
 where dev, size are the same as in the above call and cpu_addr and
 dma_handle are the values pci_alloc_consistent returned to you.
 
+If your driver needs lots of smaller memory regions, you can write
+custom code to subdivide pages returned by pci_alloc_consistent,
+or you can use the pci_pool API to do that.  A pci_pool is like
+a kmem_cache, but it uses pci_alloc_consistent not __get_free_pages.
+Also, it understands common hardware constraints for alignment,
+like queue heads needing to be aligned on N byte boundaries.
+
+Create a pci_pool like this:
+
+	struct pci_pool *pool;
+
+	pool = pci_pool_create(name, dev, size, align, alloc, flags);
+
+The "name" is for diagnostics (like a kmem_cache name); dev and size
+are as above.  The device's hardware alignment requirement for this
+type of data is "align" (a power of two).  The flags are SLAB_ flags
+as you'd pass to kmem_cache_create.  Not all flags are understood, but
+SLAB_POISON may help you find driver bugs.  If you call this in a non-
+sleeping context (f.e. in_interrupt is true or while holding SMP
+locks), pass SLAB_ATOMIC.  If your device has no boundary crossing
+restrictions, pass 0 for alloc; passing 4096 says memory allocated
+from this pool must not cross 4KByte boundaries.
+
+Allocate memory from a pci pool like this:
+
+	cpu_addr = pci_pool_alloc(pool, flags, &dma_handle);
+
+flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
+holding SMP locks), SLAB_ATOMIC otherwise.  Like pci_alloc_consistent,
+this returns two values, cpu_addr and dma_handle,
+
+Free memory that was allocated from a pci_pool like this:
+
+	pci_pool_free(pool, cpu_addr, dma_handle);
+
+where pool is what you passed to pci_pool_alloc, and cpu_addr and
+dma_handle are the values pci_pool_alloc returned.
+
+Destroy a pci_pool by calling:
+
+	pci_pool_destroy(pool);
+
+Make sure you've called pci_pool_free for all memory allocated
+from a pool before you destroy the pool.
+
 			DMA Direction
 
 The interfaces described in subsequent portions of this document
@@ -389,9 +470,10 @@
 longer, nor should they use bus_to_virt. Some drivers have to be changed a
 little bit, because there is no longer an equivalent to bus_to_virt in the
 dynamic DMA mapping scheme - you have to always store the DMA addresses
-returned by the pci_alloc_consistent and pci_map_single calls (pci_map_sg
-stores them in the scatterlist itself if the platform supports dynamic DMA
-mapping in hardware) in your driver structures and/or in the card registers.
+returned by the pci_alloc_consistent, pci_pool_alloc, and pci_map_single
+calls (pci_map_sg stores them in the scatterlist itself if the platform
+supports dynamic DMA mapping in hardware) in your driver structures and/or
+in the card registers.
 
 This document, and the API itself, would not be in it's current
 form without the feedback and suggestions from numerous individuals.
diff -u --recursive --new-file v2.4.3/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- v2.4.3/linux/Documentation/DocBook/Makefile	Sat Feb  3 12:43:55 2001
+++ linux/Documentation/DocBook/Makefile	Fri Apr  6 10:42:55 2001
@@ -1,6 +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
+	   kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \
+	   deviceiobook.sgml
 
 PS	:=	$(patsubst %.sgml, %.ps, $(BOOKS))
 PDF	:=	$(patsubst %.sgml, %.pdf, $(BOOKS))
@@ -9,12 +10,12 @@
 EPS-parportbook := $(patsubst %.fig, %.eps, $(IMG-parportbook))
 JPG-parportbook := $(patsubst %.fig, %.jpeg, $(IMG-parportbook))
 
+books:	$(BOOKS)
+
 $(BOOKS): $(TOPDIR)/scripts/docproc
 
 .PHONY:	books ps pdf html clean mrproper
 
-books:	$(BOOKS)
-
 ps:	$(PS)
 
 pdf:	$(PDF)
@@ -55,6 +56,9 @@
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/net/sis900.c \
 		<sis900.tmpl >sis900.sgml
 
+deviceiobook.sgml: deviceiobook.tmpl
+	$(TOPDIR)/scripts/docgen <deviceiobook.tmpl >deviceiobook.sgml
+
 mcabook.sgml: mcabook.tmpl $(TOPDIR)/arch/i386/kernel/mca.c
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/arch/i386/kernel/mca.c \
 		<mcabook.tmpl >mcabook.sgml
@@ -64,6 +68,7 @@
 		<videobook.tmpl >videobook.sgml
 
 APISOURCES :=	$(TOPDIR)/drivers/media/video/videodev.c \
+		$(TOPDIR)/arch/i386/kernel/irq.c \
 		$(TOPDIR)/arch/i386/kernel/mca.c \
 		$(TOPDIR)/arch/i386/kernel/mtrr.c \
 		$(TOPDIR)/drivers/char/misc.c \
@@ -77,11 +82,24 @@
 		$(TOPDIR)/drivers/net/wan/syncppp.c \
 		$(TOPDIR)/drivers/net/wan/z85230.c \
 		$(TOPDIR)/drivers/usb/usb.c \
-		$(TOPDIR)/fs/locks.c \
+		$(TOPDIR)/drivers/video/fbmem.c \
+		$(TOPDIR)/drivers/video/fbcmap.c \
+		$(TOPDIR)/drivers/video/fbcon.c \
+		$(TOPDIR)/drivers/video/fbgen.c \
+		$(TOPDIR)/drivers/video/fonts.c \
+		$(TOPDIR)/drivers/video/macmodes.c \
+		$(TOPDIR)/drivers/video/modedb.c \
 		$(TOPDIR)/fs/devfs/base.c \
+		$(TOPDIR)/fs/locks.c \
+		$(TOPDIR)/include/asm-i386/bitops.h \
 		$(TOPDIR)/kernel/pm.c \
 		$(TOPDIR)/kernel/ksyms.c \
 		$(TOPDIR)/kernel/kmod.c \
+		$(TOPDIR)/kernel/printk.c \
+		$(TOPDIR)/kernel/sched.c \
+		$(TOPDIR)/kernel/sysctl.c \
+		$(TOPDIR)/lib/string.c \
+		$(TOPDIR)/lib/vsprintf.c \
 		$(TOPDIR)/net/netsyms.c
  
 kernel-api.sgml: kernel-api.tmpl $(APISOURCES)
diff -u --recursive --new-file v2.4.3/linux/Documentation/DocBook/deviceiobook.tmpl linux/Documentation/DocBook/deviceiobook.tmpl
--- v2.4.3/linux/Documentation/DocBook/deviceiobook.tmpl	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/DocBook/deviceiobook.tmpl	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,232 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+
+<book id="DoingIO">
+ <bookinfo>
+  <title>Bus-Independent Device Accesses</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Matthew</firstname>
+    <surname>Wilcox</surname>
+    <affiliation>
+     <address>
+      <email>matthew@wil.cx</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <authorgroup>
+   <author>
+    <firstname>Alan</firstname>
+    <surname>Cox</surname>
+    <affiliation>
+     <address>
+      <email>alan@redhat.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2001</year>
+   <holder>Matthew Wilcox</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 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.
+   </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>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+	Linux provides an API which abstracts performing IO across all busses
+	and devices, allowing device drivers to be written independently of
+	bus type.
+  </para>
+  </chapter>
+
+  <chapter id="bugs">
+     <title>Known Bugs And Assumptions</title>
+  <para>
+	None.	
+  </para>
+  </chapter>
+
+  <chapter id="mmio">
+    <title>Memory Mapped IO</title>
+    <sect1>
+      <title>Getting Access to the Device</title>
+      <para>
+	The most widely supported form of IO is memory mapped IO.
+	That is, a part of the CPU's address space is interpreted
+	not as accesses to memory, but as accesses to a device.  Some
+	architectures define devices to be at a fixed address, but most
+	have some method of discovering devices.  The PCI bus walk is a
+	good example of such a scheme.	This document does not cover how
+	to receive such an address, but assumes you are starting with one.
+	Physical addresses are of type unsigned long. 
+      </para>
+
+      <para>
+	This address should not be used directly.  Instead, to get an
+	address suitable for passing to the accessor functions described
+	below, you should call <function>ioremap</function>.
+	An address suitable for accessing the device will be returned to you.
+      </para>
+
+      <para>
+	After you've finished using the device (say, in your module's
+	exit routine), call <function>iounmap</function> in order to return
+	the address space to the kernel.  Most architectures allocate new
+	address space each time you call <function>ioremap</function>, and
+	they can run out unless you call <function>iounmap</function>.
+      </para>
+    </sect1>
+
+    <sect1>
+      <title>Accessing the device</title>
+      <para>
+	The part of the interface most used by drivers is reading and
+	writing memory-mapped registers on the device.	Linux provides
+	interfaces to read and write 8-bit, 16-bit, 32-bit and 64-bit
+	quantities.  Due to a historical accident, these are named byte,
+	word, long and quad accesses.  Both read and write accesses are
+	supported; there is no prefetch support at this time.
+      </para>
+
+      <para>
+	The functions are named <function>readb</function>,
+	<function>readw</function>, <function>readl</function>,
+	<function>readq</function>, <function>writeb</function>,
+	<function>writew</function>, <function>writel</function> and
+	<function>writeq</function>.
+      </para>
+
+      <para>
+	Some devices (such as framebuffers) would like to use larger
+	transfers than 8 bytes at a time.  For these devices, the
+	<function>memcpy_toio</function>, <function>memcpy_fromio</function>
+	and <function>memset_io</function> functions are provided.
+	Do not use memset or memcpy on IO addresses; they
+	are not guaranteed to copy data in order.
+      </para>
+
+      <para>
+	The read and write functions are defined to be ordered. That is the
+	compiler is not permitted to reorder the I/O sequence. When the 
+	ordering can be compiler optimised, you can use <function>
+	__readb</function> and friends to indicate the relaxed ordering. Use 
+	this with care. The <function>rmb</function> provides a read memory 
+	barrier. The <function>wmb</function> provides a write memory barrier.
+      </para>
+
+      <para>
+	While the basic functions are defined to be synchronous with respect
+	to each other and ordered with respect to each other the busses the
+	devices sit on may themselves have asynchronocity. In paticular many
+	authors are burned by the fact that PCI bus writes are posted
+	asynchronously. A driver author must issue a read from the same
+	device to ensure that writes have occurred in the specific cases the
+	author cares. This kind of property cannot be hidden from driver
+	writers in the API.
+      </para>
+    </sect1>
+
+    <sect1>
+      <title>ISA legacy functions</title>
+      <para>
+	On older kernels (2.2 and earlier) the ISA bus could be read or
+	written with these functions and without ioremap being used. This is
+	no longer true in Linux 2.4. A set of equivalent functions exist for
+	easy legacy driver porting. The functions available are prefixed
+	with 'isa_' and are <function>isa_readb</function>,
+	<function>isa_writeb</function>, <function>isa_readw</function>, 
+	<function>isa_writew</function>, <function>isa_readl</function>,
+	<function>isa_writel</function), <function>isa_memcpy_fromio</function>
+	and <function>isa_memcpy_toio</function>
+      </para>
+      <para>
+	These functions should not be used in new drivers, and will
+	eventually be going away.
+      </para>
+    </sect1>
+
+  </chapter>
+
+  <chapter>
+    <title>Port Space Accesses</title>
+    <sect1>
+      <title>Port Space Explained</title>
+
+      <para>
+	Another form of IO commonly supported is Port Space.  This is a
+	range of addresses separate to the normal memory address space.
+	Access to these addresses is generally not as fast as accesses
+	to the memory mapped addresses, and it also has a potentially
+	smaller address space.
+      </para>
+
+      <para>
+	Unlike memory mapped IO, no preparation is required
+	to access port space.
+      </para>
+
+    </sect1>
+    <sect1>
+      <title>Accessing Port Space</title>
+      <para>
+	Accesses to this space are provided through a set of functions
+	which allow 8-bit, 16-bit and 32-bit accesses; also
+	known as byte, word and long.  These functions are
+	<function>inb</function>, <function>inw</function>,
+	<function>inl</function>, <function>outb</function>,
+	<function>outw</function> and <function>outl</function>.
+      </para>
+
+      <para>
+	Some variants are provided for these functions.  Some devices
+	require that accesses to their ports are slowed down.  This
+	functionality is provided by appending a <function>_p</function>
+	to the end of the function.  There are also equivalents to memcpy.
+	The <function>ins</function> and <function>outs</function>
+	functions copy bytes, words or longs to the given port.
+      </para>
+    </sect1>
+
+  </chapter>
+
+  <chapter id="pubfunctions">
+     <title>Public Functions Provided</title>
+!Einclude/asm-i386/io.h
+  </chapter>
+
+</book>
diff -u --recursive --new-file v2.4.3/linux/Documentation/DocBook/kernel-api.tmpl linux/Documentation/DocBook/kernel-api.tmpl
--- v2.4.3/linux/Documentation/DocBook/kernel-api.tmpl	Fri Mar  2 18:43:10 2001
+++ linux/Documentation/DocBook/kernel-api.tmpl	Fri Apr  6 10:42:55 2001
@@ -36,7 +36,7 @@
 <toc></toc>
 
   <chapter id="Basics">
-     <title>Driver Basic</title>
+     <title>Driver Basics</title>
      <sect1><title>Driver Entry and Exit points</title>
 !Iinclude/linux/init.h
      </sect1>
@@ -44,6 +44,10 @@
      <sect1><title>Atomics</title>
 !Iinclude/asm-i386/atomic.h
      </sect1>
+
+     <sect1><title>Delaying, scheduling, and timer routines</title>
+!Ekernel/sched.c
+     </sect1>
   </chapter>
 
   <chapter id="adt">
@@ -53,6 +57,29 @@
      </sect1>
   </chapter>
 
+  <chapter id="libc">
+     <title>Basic C Library Functions</title>
+
+     <para>
+       When writing drivers, you cannot in general use routines which are
+       from the C Library.  Some of the functions have been found generally
+       useful and they are listed below.  The behaviour of these functions
+       may vary slightly from those defined by ANSI, and these deviations
+       are noted in the text.
+     </para>
+
+     <sect1><title>String Conversions</title>
+!Ilib/vsprintf.c
+!Elib/vsprintf.c
+     </sect1>
+     <sect1><title>String Manipulation</title>
+!Ilib/string.c
+     </sect1>
+     <sect1><title>Bit Operations</title>
+!Iinclude/asm-i386/bitops.h
+     </sect1>
+  </chapter>
+
   <chapter id="mm">
      <title>Memory Management in Linux</title>
      <sect1><title>The Slab Cache</title>
@@ -60,6 +87,14 @@
       </sect1>
   </chapter>
 
+  <chapter id="proc">
+     <title>The proc filesystem</title>
+ 
+     <sect1><title>sysctl interface</title>
+!Ekernel/sysctl.c
+     </sect1>
+  </chapter>
+
   <chapter id="vfs">
      <title>The Linux VFS</title>
      <sect1><title>The Directory Cache</title>
@@ -177,5 +212,68 @@
 !Edrivers/net/wan/z85230.c
   </chapter>
 
+  <chapter id="fbdev">
+     <title>Frame Buffer Library</title>
+
+     <para>
+       The frame buffer drivers depend heavily on four data structures.  
+       These structures are declared in include/linux/fb.h.  They are 
+       fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs. 
+       The last three can be made available to and from userland. 
+     </para>
+
+     <para>
+       fb_info defines the current state of a particular video card. 
+       Inside fb_info, there exists a fb_ops structure which is a 
+       collection of needed functions to make fbdev and fbcon work.
+       fb_info is only visible to the kernel.
+     </para>
+
+     <para>
+       fb_var_screeninfo is used to describe the features of a video card 
+       that are user defined.  With fb_var_screeninfo, things such as
+       depth and the resolution may be defined.
+     </para>
+
+     <para>
+       The next structure is fb_fix_screeninfo. This defines the 
+       properties of a card that are created when a mode is set and can't 
+       be changed otherwise.  A good example of this is the start of the 
+       frame buffer memory.  This "locks" the address of the frame buffer
+       memory, so that it cannot be changed or moved.
+     </para>
+
+     <para>
+       The last structure is fb_monospecs. In the old API, there was 
+       little importance for fb_monospecs. This allowed for forbidden things 
+       such as setting a mode of 800x600 on a fix frequency monitor. With 
+       the new API, fb_monospecs prevents such things, and if used 
+       correctly, can prevent a monitor from being cooked.  fb_monospecs
+       will not be useful until kernels 2.5.x.
+     </para>
+
+     <sect1><title>Frame Buffer Memory</title>
+!Edrivers/video/fbmem.c
+     </sect1>
+     <sect1><title>Frame Buffer Console</title>
+!Edrivers/video/fbcon.c
+     </sect1>
+     <sect1><title>Frame Buffer Colormap</title>
+!Edrivers/video/fbcmap.c
+     </sect1>
+     <sect1><title>Frame Buffer Generic Functions</title>
+!Idrivers/video/fbgen.c
+     </sect1>
+     <sect1><title>Frame Buffer Video Mode Database</title>
+!Idrivers/video/modedb.c
+!Edrivers/video/modedb.c
+     </sect1>
+     <sect1><title>Frame Buffer Macintosh Video Mode Database</title>
+!Idrivers/video/macmodes.c
+     </sect1>
+     <sect1><title>Frame Buffer Fonts</title>
+!Idrivers/video/fonts.c
+     </sect1>
+  </chapter>
 
 </book>
diff -u --recursive --new-file v2.4.3/linux/Documentation/DocBook/kernel-hacking.tmpl linux/Documentation/DocBook/kernel-hacking.tmpl
--- v2.4.3/linux/Documentation/DocBook/kernel-hacking.tmpl	Thu Feb  8 16:32:44 2001
+++ linux/Documentation/DocBook/kernel-hacking.tmpl	Fri Apr  6 10:42:55 2001
@@ -11,7 +11,7 @@
     <surname>Russell</surname>
     <affiliation>
      <address>
-      <email>rusty@linuxcare.com</email>
+      <email>rusty@rustcorp.com.au</email>
      </address>
     </affiliation>
    </author>
@@ -336,6 +336,11 @@
   </para>
 
   <para>
+   If all your routine does is read or write some parameter, consider
+   implementing a <function>sysctl</function> interface instead.
+  </para>
+
+  <para>
    Inside the ioctl you're in user context to a process.  When a
    error occurs you return a negated errno (see
    <filename class=headerfile>include/linux/errno.h</filename>),
@@ -407,7 +412,7 @@
   <para>
    Note that some functions may sleep implicitly: common ones are
    the user space access functions (*_user) and memory allocation
-   functions without GFP_ATOMIC.
+   functions without <symbol>GFP_ATOMIC</symbol>.
   </para>
 
   <para>
@@ -608,7 +613,8 @@
     for some weird device, you have a problem: it is poorly supported
     in Linux because after some time memory fragmentation in a running
     kernel makes it hard.  The best way is to allocate the block early
-    in the boot process.
+    in the boot process via the <function>alloc_bootmem()</function>
+    routine.
    </para>
 
    <para>
@@ -631,6 +637,20 @@
    </para>
   </sect1>
 
+  <sect1 id="routines-udelay">
+   <title><function>udelay()</function>/<function>mdelay()</function>
+     <filename class=headerfile>include/asm/delay.h</filename> 
+     <filename class=headerfile>include/linux/delay.h</filename> 
+   </title>
+
+   <para>
+    The <function>udelay()</function> function can be used for small pauses.
+    Do not use large values with <function>udelay()</function> as you risk
+    overflow - the helper function <function>mdelay()</function> is useful
+    here, or even consider <function>schedule_timeout()</function>.
+   </para> 
+  </sect1>
+ 
   <sect1 id="routines-local-irqs">
    <title><function>local_irq_save()</function>/<function>local_irq_restore()</function>
     <filename class=headerfile>include/asm/system.h</filename>
@@ -687,8 +707,14 @@
     modules this directive is currently ignored).  <type>__exit</type>
     is used to declare a function which is only required on exit: the
     function will be dropped if this file is not compiled as a module.
-    See the header file for use.
+    See the header file for use. Note that it makes no sense for a function
+    marked with <type>__init</type> to be exported to modules with 
+    <function>EXPORT_SYMBOL()</function> - this will break.
    </para>
+   <para>
+   Static data structures marked as <type>__initdata</type> must be initialised
+   (as opposed to ordinary static data which is zeroed BSS).
+   </para> 
 
   </sect1>
 
@@ -775,6 +801,21 @@
         return 0;
 }
    </programlisting>
+
+   <para>
+   You can often avoid having to deal with these problems by using the 
+   <structfield>owner</structfield> field of the 
+   <structname>file_operations</structname> structure. Set this field
+   as the macro <symbol>THIS_MODULE</symbol>.
+   </para>
+
+   <para>
+   For more complicated module unload locking requirements, you can set the
+   <structfield>can_unload</structfield> function pointer to your own routine,
+   which should return <returnvalue>0</returnvalue> if the module is
+   unloadable, or <returnvalue>-EBUSY</returnvalue> otherwise.
+   </para> 
+  
   </sect1>
  </chapter>
 
@@ -822,6 +863,17 @@
     <returnvalue>-ERESTARTSYS</returnvalue> if a signal is received.
     The <function>wait_event()</function> version ignores signals.
    </para>
+   <para>
+   Do not use the <function>sleep_on()</function> function family -
+   it is very easy to accidentally introduce races; almost certainly
+   one of the <function>wait_event()</function> family will do, or a
+   loop around <function>schedule_timeout()</function>. If you choose
+   to loop around <function>schedule_timeout()</function> remember
+   you must set the task state (with 
+   <function>set_current_state()</function>) on each iteration to avoid
+   busy-looping.
+   </para>
+ 
   </sect1>
 
   <sect1 id="queue-waking">
@@ -1212,6 +1264,13 @@
      <filename>MAINTAINERS</filename> means you want to be consulted
      when changes are made to a subsystem, and hear about bugs; it
      implies a more-than-passing commitment to some part of the code.
+    </para>
+   </listitem>
+   
+   <listitem>
+    <para>
+     Finally, don't forget to read <filename>Documentation/SubmittingPatches</filename>
+     and possibly <filename>Documentation/SubmittingDrivers</filename>.
     </para>
    </listitem>
   </itemizedlist>
diff -u --recursive --new-file v2.4.3/linux/Documentation/DocBook/kernel-locking.tmpl linux/Documentation/DocBook/kernel-locking.tmpl
--- v2.4.3/linux/Documentation/DocBook/kernel-locking.tmpl	Fri Feb 16 15:53:08 2001
+++ linux/Documentation/DocBook/kernel-locking.tmpl	Fri Apr  6 10:42:55 2001
@@ -11,7 +11,7 @@
     <surname>Russell</surname>
     <affiliation>
      <address>
-      <email>rusty@linuxcare.com</email>
+      <email>rusty@rustcorp.com.au</email>
      </address>
     </affiliation>
    </author>
diff -u --recursive --new-file v2.4.3/linux/Documentation/DocBook/parportbook.tmpl linux/Documentation/DocBook/parportbook.tmpl
--- v2.4.3/linux/Documentation/DocBook/parportbook.tmpl	Wed Jul 12 16:24:33 2000
+++ linux/Documentation/DocBook/parportbook.tmpl	Thu Apr 12 12:05:50 2001
@@ -2079,7 +2079,7 @@
                               | PARPORT_STATUS_BUSY);
         unsigned char val = (PARPORT_STATUS_ERROR
                               | PARPORT_STATUS_BUSY);
-        struct parport_frob_struct frob;
+        struct ppdev_frob_struct frob;
         struct timespec ts;
 
         /* Wait for printer to be ready */
diff -u --recursive --new-file v2.4.3/linux/Documentation/DocBook/tulip-user.tmpl linux/Documentation/DocBook/tulip-user.tmpl
--- v2.4.3/linux/Documentation/DocBook/tulip-user.tmpl	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/DocBook/tulip-user.tmpl	Wed Apr 18 14:40:06 2001
@@ -0,0 +1,325 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+
+<book id="TulipUserGuide">
+ <bookinfo>
+  <title>Tulip Driver User's Guide</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Jeff</firstname>
+    <surname>Garzik</surname>
+    <affiliation>
+     <address>
+      <email>jgarzik@mandrakesoft.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2001</year>
+   <holder>Jeff Garzik</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 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.
+   </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>
+
+  <chapter id="intro">
+    <title>Introduction</title>
+<para>
+The Tulip Ethernet Card Driver
+is maintained by Jeff Garzik (<email>jgarzik@mandrakesoft.com</email>).
+</para>
+
+<para>
+The Tulip driver was developed by Donald Becker and changed by
+Jeff Garzik, Takashi Manabe and a cast of thousands.
+</para>
+
+<para>
+For 2.4.x and later kernels, the Linux Tulip driver is available at
+<ULink URL="http://sourceforge.net/projects/tulip/">http://sourceforge.net/projects/tulip/</ULink>
+</para>
+
+<para>
+	This driver is for the Digital "Tulip" Ethernet adapter interface.
+	It should work with most DEC 21*4*-based chips/ethercards, as well as
+	with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
+</para>
+
+<para>
+        The original author may be reached as becker@scyld.com, or C/O
+        Scyld Computing Corporation,
+        410 Severn Ave., Suite 210,
+        Annapolis MD 21403
+</para>
+
+<para>
+	Additional information on Donald Becker's tulip.c
+	is available at <ULink URL="http://www.scyld.com/network/tulip.html">http://www.scyld.com/network/tulip.html</ULink>
+</para>
+
+  </chapter>
+
+  <chapter id="drvr_compat">
+    <title>Driver Compatibility</title>
+
+<para>
+This device driver is designed for the DECchip "Tulip", Digital's
+single-chip ethernet controllers for PCI (now owned by Intel).
+Supported members of the family
+are the 21040, 21041, 21140, 21140A, 21142, and 21143.  Similar work-alike
+chips from Lite-On, Macronics, ASIX, Compex and other listed below are also
+supported.
+</para>
+
+<para>
+These chips are used on at least 140 unique PCI board designs.  The great
+number of chips and board designs supported is the reason for the
+driver size and complexity.  Almost of the increasing complexity is in the
+board configuration and media selection code.  There is very little
+increasing in the operational critical path length.
+</para>
+  </chapter>
+
+  <chapter id="board_settings">
+    <title>Board-specific Settings</title>
+
+<para>
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS preferably should assign the
+PCI INTA signal to an otherwise unused system IRQ line.
+</para>
+
+<para>
+Some boards have EEPROMs tables with default media entry.  The factory default
+is usually "autoselect".  This should only be overridden when using
+transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
+for forcing full-duplex when used with old link partners that do not do
+autonegotiation.
+</para>
+  </chapter>
+
+  <chapter id="driver_operation">
+    <title>Driver Operation</title>
+
+<sect1><title>Ring buffers</title>
+
+<para>
+The Tulip can use either ring buffers or lists of Tx and Rx descriptors.
+This driver uses statically allocated rings of Rx and Tx descriptors, set at
+compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
+for the Rx ring buffers at open() time and passes the skb->data field to the
+Tulip as receive data buffers.  When an incoming frame is less than
+RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
+copied to the new skbuff.  When the incoming frame is larger, the skbuff is
+passed directly up the protocol stack and replaced by a newly allocated
+skbuff.
+</para>
+
+<para>
+The RX_COPYBREAK value is chosen to trade-off the memory wasted by
+using a full-sized skbuff for small frames vs. the copying costs of larger
+frames.  For small frames the copying cost is negligible (esp. considering
+that we are pre-loading the cache with immediately useful header
+information).  For large frames the copying cost is non-trivial, and the
+larger copy might flush the cache of useful data.  A subtle aspect of this
+choice is that the Tulip only receives into longword aligned buffers, thus
+the IP header at offset 14 isn't longword aligned for further processing.
+Copied frames are put into the new skbuff at an offset of "+2", thus copying
+has the beneficial effect of aligning the IP header and preloading the
+cache.
+</para>
+
+</sect1>
+
+<sect1><title>Synchronization</title>
+<para>
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag.  The other thread is the interrupt handler, which is single
+threaded by the hardware and other software.
+</para>
+
+<para>
+The send packet thread has partial control over the Tx ring and 'dev->tbusy'
+flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
+queue slot is empty, it clears the tbusy flag when finished otherwise it sets
+the 'tp->tx_full' flag.
+</para>
+
+<para>
+The interrupt handler has exclusive control over the Rx ring and records stats
+from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
+we can't avoid the interrupt overhead by having the Tx routine reap the Tx
+stats.)	 After reaping the stats, it marks the queue entry as empty by setting
+the 'base' to zero.	 Iff the 'tp->tx_full' flag is set, it clears both the
+tx_full and tbusy flags.
+</para>
+
+</sect1>
+
+  </chapter>
+
+  <chapter id="errata">
+    <title>Errata</title>
+
+<para>
+The old DEC databooks were light on details.
+The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
+register of the set CSR12-15 written.  Hmmm, now how is that possible?
+</para>
+
+<para>
+The DEC SROM format is very badly designed not precisely defined, leading to
+part of the media selection junkheap below.  Some boards do not have EEPROM
+media tables and need to be patched up.  Worse, other boards use the DEC
+design kit media table when it isn't correct for their board.
+</para>
+
+<para>
+We cannot use MII interrupts because there is no defined GPIO pin to attach
+them.  The MII transceiver status is polled using an kernel timer.
+</para>
+  </chapter>
+
+  <chapter id="changelog">
+    <title>Driver Change History</title>
+
+    <sect1><title>Version 0.9.14 (February 20, 2001)</title>
+    <itemizedlist>
+    <listitem><para>Fix PNIC problems (Manfred Spraul)</para></listitem>
+    <listitem><para>Add new PCI id for Accton comet</para></listitem>
+    <listitem><para>Support Davicom tulips</para></listitem>
+    <listitem><para>Fix oops in eeprom parsing</para></listitem>
+    <listitem><para>Enable workarounds for early PCI chipsets</para></listitem>
+    <listitem><para>IA64, hppa csr0 support</para></listitem>
+    <listitem><para>Support media types 5, 6</para></listitem>
+    <listitem><para>Interpret a bit more of the 21142 SROM extended media type 3</para></listitem>
+    <listitem><para>Add missing delay in eeprom reading</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.11 (November 3, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Eliminate extra bus accesses when sharing interrupts (prumpf)</para></listitem>
+    <listitem><para>Barrier following ownership descriptor bit flip (prumpf)</para></listitem>
+    <listitem><para>Endianness fixes for >14 addresses in setup frames (prumpf)</para></listitem>
+    <listitem><para>Report link beat to kernel/userspace via netif_carrier_*. (kuznet)</para></listitem>
+    <listitem><para>Better spinlocking in set_rx_mode.</para></listitem>
+    <listitem><para>Fix I/O resource request failure error messages (DaveM catch)</para></listitem>
+    <listitem><para>Handle DMA allocation failure.</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.10 (September 6, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Simple interrupt mitigation (via jamal)</para></listitem>
+    <listitem><para>More PCI ids</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.9 (August 11, 2000)</title>
+    <itemizedlist>
+    <listitem><para>More PCI ids</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.8 (July 13, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Correct signed/unsigned comparison for dummy frame index</para></listitem>
+    <listitem><para>Remove outdated references to struct enet_statistics</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.7 (June 17, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Timer cleanups (Andrew Morton)</para></listitem>
+    <listitem><para>Alpha compile fix (somebody?)</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.6 (May 31, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Revert 21143-related support flag patch</para></listitem>
+    <listitem><para>Add HPPA/media-table debugging printk</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.5 (May 30, 2000)</title>
+    <itemizedlist>
+    <listitem><para>HPPA support (willy@puffingroup)</para></listitem>
+    <listitem><para>CSR6 bits and tulip.h cleanup (Chris Smith)</para></listitem>
+    <listitem><para>Improve debugging messages a bit</para></listitem>
+    <listitem><para>Add delay after CSR13 write in t21142_start_nway</para></listitem>
+    <listitem><para>Remove unused ETHER_STATS code</para></listitem>
+    <listitem><para>Convert 'extern inline' to 'static inline' in tulip.h (Chris Smith)</para></listitem>
+    <listitem><para>Update DS21143 support flags in tulip_chip_info[]</para></listitem>
+    <listitem><para>Use spin_lock_irq, not _irqsave/restore, in tulip_start_xmit()</para></listitem>
+    <listitem><para>Add locking to set_rx_mode()</para></listitem>
+    <listitem><para>Fix race with chip setting DescOwned bit (Hal Murray)</para></listitem>
+    <listitem><para>Request 100% of PIO and MMIO resource space assigned to card</para></listitem>
+    <listitem><para>Remove error message from pci_enable_device failure</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.4.3 (April 14, 2000)</title>
+    <itemizedlist>
+    <listitem><para>mod_timer fix (Hal Murray)</para></listitem>
+    <listitem><para>PNIC2 resuscitation (Chris Smith)</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.4.2 (March 21, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Fix 21041 CSR7, CSR13/14/15 handling</para></listitem>
+    <listitem><para>Merge some PCI ids from tulip 0.91x</para></listitem>
+    <listitem><para>Merge some HAS_xxx flags and flag settings from tulip 0.91x</para></listitem>
+    <listitem><para>asm/io.h fix (submitted by many) and cleanup</para></listitem>
+    <listitem><para>s/HAS_NWAY143/HAS_NWAY/</para></listitem>
+    <listitem><para>Cleanup 21041 mode reporting</para></listitem>
+    <listitem><para>Small code cleanups</para></listitem>
+    </itemizedlist>
+    </sect1>
+
+    <sect1><title>Version 0.9.4.1 (March 18, 2000)</title>
+    <itemizedlist>
+    <listitem><para>Finish PCI DMA conversion (davem)</para></listitem>
+    <listitem><para>Do not netif_start_queue() at end of tulip_tx_timeout() (kuznet)</para></listitem>
+    <listitem><para>PCI DMA fix (kuznet)</para></listitem>
+    <listitem><para>eeprom.c code cleanup</para></listitem>
+    <listitem><para>Remove Xircom Tulip crud</para></listitem>
+    </itemizedlist>
+    </sect1>
+  </chapter>
+
+</book>
diff -u --recursive --new-file v2.4.3/linux/Documentation/SubmittingDrivers linux/Documentation/SubmittingDrivers
--- v2.4.3/linux/Documentation/SubmittingDrivers	Thu Feb  8 16:32:44 2001
+++ linux/Documentation/SubmittingDrivers	Fri Apr  6 10:42:55 2001
@@ -111,7 +111,7 @@
 
 Kernel traffic:
 	Weekly summary of kernel list activity (much easier to read)
-	[http://kt.linuxcare.com/kernel-traffic]
+	[http://kt.zork.net/kernel-traffic]
 
 Linux USB project:
 	http://sourceforge.net/projects/linux-usb/
diff -u --recursive --new-file v2.4.3/linux/Documentation/arm/README linux/Documentation/arm/README
--- v2.4.3/linux/Documentation/arm/README	Mon Nov 27 17:07:59 2000
+++ linux/Documentation/arm/README	Wed Apr 11 19:02:27 2001
@@ -1,5 +1,5 @@
-			   ARM Linux 2.4.0test1
-			   ====================
+			   ARM Linux 2.4
+			   =============
 
     Please check ftp.arm.linux.org.uk:/pub/armlinux for latest updates.
 
@@ -7,9 +7,8 @@
 ---------------------
 
   In order to compile ARM Linux, you will need a compiler capable of
-  generating ARM ELF code with GNU extensions.  GCC-2.7.2.2 ELF, GCC 2.8.1
-  and EGCS are good compilers.  Note that GCC-2.7.2.2 ELF is rare, and
-  you probably don't have it.
+  generating ARM ELF code with GNU extensions.  GCC 2.95.1 and EGCS 1.1.2
+  are good compilers.
 
   To build ARM Linux natively, you shouldn't have to alter the ARCH = line
   in the top level Makefile.  However, if you don't have the ARM Linux ELF
@@ -166,4 +165,4 @@
   receive a reply within one day.
 
 ---
-Russell King (12/06/2000)
+Russell King (26/01/2001)
diff -u --recursive --new-file v2.4.3/linux/Documentation/cris/README linux/Documentation/cris/README
--- v2.4.3/linux/Documentation/cris/README	Thu Feb  8 16:32:44 2001
+++ linux/Documentation/cris/README	Fri Apr  6 10:42:55 2001
@@ -1,20 +1,22 @@
 Linux 2.4 on the CRIS architecture
 ==================================
-$Id: README,v 1.5 2001/01/10 17:20:55 bjornw Exp $
+$Id: README,v 1.6 2001/02/21 15:27:25 bjornw Exp $
 
-This is a port of Linux 2.4 to Axis Communications ETRAX 100LX embedded network CPU. For
-more information about CRIS and ETRAX please see further below.
+This is a port of Linux 2.4 to Axis Communications ETRAX 100LX embedded 
+network CPU. For more information about CRIS and ETRAX please see further
+below.
 
-<... to come: instructions on how to grab the right gcc, compiling and booting ...>
+<to come: instructions on how to grab the right gcc, compiling and booting>
 
 
 What is CRIS ?
 --------------
 
-CRIS is an acronym for 'Code Reduced Instruction Set'. It is the CPU architecture in Axis
-Communication AB's range of embedded network CPU's, called ETRAX. The latest CPU is called
-ETRAX 100LX, where LX stands for 'Linux' because the chip was designed to be a good host for
-the Linux operating system.
+CRIS is an acronym for 'Code Reduced Instruction Set'. It is the CPU
+architecture in Axis Communication AB's range of embedded network CPU's,
+called ETRAX. The latest CPU is called ETRAX 100LX, where LX stands for
+'Linux' because the chip was designed to be a good host for the Linux
+operating system.
 
 The ETRAX 100LX chip
 --------------------
@@ -23,8 +25,8 @@
 
 http://www.axis.com/news/us/001101_etrax.htm
 
-The ETRAX 100LX is a 100 MIPS processor with 8kB cache, MMU, and a very broad range of 
-built-in interfaces, all with modern scatter/gather DMA.
+The ETRAX 100LX is a 100 MIPS processor with 8kB cache, MMU, and a very broad 
+range of  built-in interfaces, all with modern scatter/gather DMA.
 
 Memory interfaces:
 
@@ -44,40 +46,41 @@
 	* two parallel-ports
 	* two generic 8-bit ports
 	
-	(not all interfaces are available at the same time due to chip pin multiplexing)
+	(not all interfaces are available at the same time due to chip pin 
+         multiplexing)
 
-The previous version of the ETRAX, the ETRAX 100, sits in almost all of Axis shipping 
-thin-servers like the Axis 2100 web camera or the developer-board. It lacks an MMU so the
-Linux we run on that is a version of uClinux (Linux 2.0 without MM-support) ported to the CRIS
-architecture. The new Linux 2.4 port has full MM and needs a CPU with an MMU, so it will not
-run on the ETRAX 100. 
-
-A version of the Axis developer-board with ETRAX 100LX will be available as soon as the chip 
-is ramped up (please see http://developer.axis.com for further information on that).
+The previous version of the ETRAX, the ETRAX 100, sits in almost all of
+Axis shipping thin-servers like the Axis 2100 web camera or the ETRAX 100
+developer-board. It lacks an MMU so the Linux we run on that is a version
+of uClinux (Linux 2.0 without MM-support) ported to the CRIS architecture.
+The new Linux 2.4 port has full MM and needs a CPU with an MMU, so it will
+not run on the ETRAX 100.
 
+A version of the Axis developer-board with ETRAX 100LX (running Linux
+2.4) is now available. For more information please see developer.axis.com.
 
 
 Bootlog
 -------
 
-Just as an example, this is the debug-output from a boot of Linux 2.4 on an Axis
-developer-board with ETRAX 100LX. The displayed BogoMIPS value is 5 times too small :)
+Just as an example, this is the debug-output from a boot of Linux 2.4 on
+a board with ETRAX 100LX. The displayed BogoMIPS value is 5 times too small :)
 At the end you see some user-mode programs booting like telnet and ftp daemons.
 
-Linux version 2.4.0-test11 (bjornw@godzilla.axis.se) (gcc version 2.96 20000427 (experimental)) #358 Wed Nov 22 19:29:15 CET 2000
-ROM fs in RAM, size 368640 bytes
+Linux version 2.4.1 (bjornw@godzilla.axis.se) (gcc version 2.96 20000427 (experimental)) #207 Wed Feb 21 15:48:15 CET 2001
+ROM fs in RAM, size 1376256 bytes
 Setting up paging and the MMU.
-On node 0 totalpages: 1024
-zone(0): 1024 pages.
+On node 0 totalpages: 2048
+zone(0): 2048 pages.
 zone(1): 0 pages.
 zone(2): 0 pages.
-Linux/CRIS port (c) 2000 Axis Communications AB
+Linux/CRIS port on ETRAX 100LX (c) 2001 Axis Communications AB
 Kernel command line: 
-Calibrating delay loop... 19.92 BogoMIPS
-Memory: 6864k/8192k available (531k kernel code, 1328k reserved, 85k data, 24k init)
+Calibrating delay loop... 19.91 BogoMIPS
+Memory: 13872k/16384k available (587k kernel code, 2512k reserved, 44k data, 24k init)
 kmem_create: Forcing size word alignment - vm_area_struct
 kmem_create: Forcing size word alignment - filp
-Dentry-cache hash table entries: 1024 (order: 0, 8192 bytes)
+Dentry-cache hash table entries: 2048 (order: 1, 16384 bytes)
 Buffer-cache hash table entries: 2048 (order: 0, 8192 bytes)
 Page-cache hash table entries: 2048 (order: 0, 8192 bytes)
 kmem_create: Forcing size word alignment - kiobuf
@@ -87,41 +90,52 @@
 POSIX conformance testing by UNIFIX
 Linux NET4.0 for Linux 2.4
 Based upon Swansea University Computer Society NET3.039
-kmem_create: Forcing size word alignment - skbuff_head_cache
 Starting kswapd v1.8
 kmem_create: Forcing size word alignment - file lock cache
 kmem_create: Forcing size word alignment - blkdev_requests
+block: queued sectors max/low 9109kB/3036kB, 64 slots per queue
 ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000 Axis Communications AB
 eth0 initialized
 eth0: changed MAC to 00:40:8C:CD:00:00
-ETRAX 100LX serial-driver $Revision: 1.5 $, (c) 2000 Axis Communications AB
+ETRAX 100LX serial-driver $Revision: 1.6 $, (c) 2000 Axis Communications AB
 ttyS0 at 0xb0000060 is a builtin UART with DMA
 ttyS1 at 0xb0000068 is a builtin UART with DMA
 ttyS2 at 0xb0000070 is a builtin UART with DMA
 ttyS3 at 0xb0000078 is a builtin UART with DMA
+Axis flash mapping: 200000 at 50000000
+Axis flash: Found 1 x16 CFI device at 0x0 in 16 bit mode
+ Amd/Fujitsu Extended Query Table v1.0 at 0x0040
+Axis flash: JEDEC Device ID is 0xC4. Assuming broken CFI table.
+Axis flash: Swapping erase regions for broken CFI table.
+number of CFI chips: 1
+ Using default partition table
+I2C driver v2.2, (c) 1999-2001 Axis Communications AB
+ETRAX 100LX GPIO driver v2.1, (c) 2001 Axis Communications AB
 NET4: Linux TCP/IP 1.0 for NET4.0
 IP Protocols: ICMP, UDP, TCP
 kmem_create: Forcing size word alignment - ip_dst_cache
 IP: routing cache hash table of 1024 buckets, 8Kbytes
-TCP: Hash tables configured (established 1024 bind 1024)
+TCP: Hash tables configured (established 2048 bind 2048)
 NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
 VFS: Mounted root (cramfs filesystem) readonly.
 Init starts up...
+Mounted none on /proc ok.
 Setting up eth0 with ip 10.13.9.116 and mac 00:40:8c:18:04:60
 eth0: changed MAC to 00:40:8C:18:04:60
 Setting up lo with ip 127.0.0.1
 Default gateway is 10.13.9.1
 Hostname is bbox1
 Telnetd starting, using port 23.
-  using /bin/sh as shell.
-sftpd[14]: sftpd $Revision: 1.5 $ starting up
+  using /bin/sash as shell.
+sftpd[15]: sftpd $Revision: 1.6 $ starting up
+
 
 
 And here is how some /proc entries look:
 
 17# cd /proc
 17# cat cpuinfo
-cpu             : ETRAX
+cpu             : CRIS
 cpu revision    : 10
 cpu model       : ETRAX 100LX
 cache size      : 8 kB
@@ -133,6 +147,7 @@
 ata             : yes
 usb             : yes
 bogomips        : 99.84
+
 17# cat meminfo
         total:    used:    free:  shared: buffers:  cached:
 Mem:   7028736   925696  6103040   114688        0   229376
diff -u --recursive --new-file v2.4.3/linux/Documentation/dnotify.txt linux/Documentation/dnotify.txt
--- v2.4.3/linux/Documentation/dnotify.txt	Fri Mar  2 18:38:37 2001
+++ linux/Documentation/dnotify.txt	Fri Apr  6 10:42:48 2001
@@ -1,7 +1,7 @@
 		Linux Directory Notification
 		============================
 
-	   Stephen Rothwell <sfr@linuxcare.com.au>
+	   Stephen Rothwell <sfr@canb.auug.org.au>
 
 The intention of directory notification is to allow user applications
 to be notified when a directory, or any of the files in it, are changed.
diff -u --recursive --new-file v2.4.3/linux/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog
--- v2.4.3/linux/Documentation/filesystems/devfs/ChangeLog	Wed Jul  5 21:36:49 2000
+++ linux/Documentation/filesystems/devfs/ChangeLog	Fri Apr  6 10:42:48 2001
@@ -495,7 +495,7 @@
 
 - Replaced dummy .epoch inode with .devfsd character device
 
-- Modified rc.devfs to take acount of above change
+- Modified rc.devfs to take account of above change
 
 - Removed spurious driver warning messages when CONFIG_DEVFS_FS=n
 
diff -u --recursive --new-file v2.4.3/linux/Documentation/filesystems/ext2.txt linux/Documentation/filesystems/ext2.txt
--- v2.4.3/linux/Documentation/filesystems/ext2.txt	Sun Oct  1 20:21:20 2000
+++ linux/Documentation/filesystems/ext2.txt	Fri Apr 20 16:18:35 2001
@@ -4,7 +4,7 @@
 
 ext2 was originally released in January 1993.  Written by R\'emy Card,
 Theodore Ts'o and Stephen Tweedie, it was a major rewrite of the
-Extended Filesystem.  It is currently (February 1999) the predominant
+Extended Filesystem.  It is currently still (April 2001) the predominant
 filesystem in use by Linux.  There are also implementations available
 for NetBSD, FreeBSD, the GNU HURD, Windows 95/98/NT, OS/2 and RISC OS.
 
@@ -17,11 +17,11 @@
 bsddf			(*)	Makes `df' act like BSD.
 minixdf				Makes `df' act like Minix.
 
-check=none, nocheck		Perform no checks upon the filesystem.
-check=normal		(*)	Perform normal checks on the filesystem.
-check=strict			Perform extra checks on the filesystem.
+check=none, nocheck	(*)	Don't do extra checking of bitmaps on mount
+				(check=normal and check=strict options removed)
 
-debug				For developers only.
+debug				Extra debugging information is sent to the
+				kernel syslog.  Useful for developers.
 
 errors=continue		(*)	Keep going on a filesystem error.
 errors=remount-ro		Remount the filesystem read-only on an error.
@@ -30,8 +30,8 @@
 grpid, bsdgroups		Give objects the same group ID as their parent.
 nogrpid, sysvgroups	(*)	New objects have the group ID of their creator.
 
-resuid=n			The user which may use the reserved blocks.
-resgid=n			The group which may use the reserved blocks. 
+resuid=n			The user ID which may use the reserved blocks.
+resgid=n			The group ID which may use the reserved blocks. 
 
 sb=n				Use alternate superblock at this location.
 
@@ -53,46 +53,53 @@
 ------
 
 The space in the device or file is split up into blocks.  These are
-a fixed size, of 1024, 2048 or 4096 bytes, which is decided when the
-filesystem is created.  Smaller blocks mean less wasted space per file,
-but require slightly more accounting overhead.
+a fixed size, of 1024, 2048 or 4096 bytes (8192 bytes on Alpha systems),
+which is decided when the filesystem is created.  Smaller blocks mean
+less wasted space per file, but require slightly more accounting overhead,
+and also impose other limits on the size of files and the filesystem.
+
+Block Groups
+------------
 
 Blocks are clustered into block groups in order to reduce fragmentation
-and minimise the amount of head seeking when reading a large amount of
-consecutive data.  Each block group has a descriptor and the array of
-descriptors is stored immediately after the superblock.  Two blocks at
-the start of each group are reserved for the block usage bitmap and
-the inode usage bitmap which show which blocks and inodes are used.
-Since each bitmap fits in a block, this means that the maximum size of
-a block group is 8 times the size of a block.
-
-The first (non-reserved) blocks in the block group are designated as
-the inode table for the block and the remainder are the data blocks.
-The block allocation algorithm attempts to allocate data blocks in the
-same block group as the inode which contains them.
+and minimise the amount of head seeking when reading a large amount
+of consecutive data.  Information about each block group is kept in a
+descriptor table stored in the block(s) immediately after the superblock.
+Two blocks near the start of each group are reserved for the block usage
+bitmap and the inode usage bitmap which show which blocks and inodes
+are in use.  Since each bitmap is limited to a single block, this means
+that the maximum size of a block group is 8 times the size of a block.
+
+The block(s) following the bitmaps in each block group are designated
+as the inode table for that block group and the remainder are the data
+blocks.  The block allocation algorithm attempts to allocate data blocks
+in the same block group as the inode which contains them.
 
 The Superblock
 --------------
 
 The superblock contains all the information about the configuration of
-the filing system.  It is stored in block 1 of the filesystem (numbering
-from 0) and it is essential to mounting it.  Since it is so important,
-backup copies of the superblock are stored in block groups throughout
-the filesystem.  The first revision of ext2 stores a copy at the start
-of every block group.  Later revisions can store a copy in only some
-block groups to reduce the amount of redundancy on large filesystems.
-The groups chosen are 0, 1 and powers of 3, 5 and 7.
-
-The information in the superblock contains fields such as how many
-inodes and blocks are in the filesystem and how many are unused, how
-many inodes and blocks are in a block group, when the filesystem was
-mounted, when it was modified, what version of the filesystem it is
-(see the Revisions section below) and which OS created it.
-
-If the revision of the filesystem is recent enough then there are extra
-fields, such as a volume name, a unique identifier, the inode size,
-support for compression, block preallocation and creating fewer backup
-superblocks.
+the filing system.  The primary copy of the superblock is stored at an
+offset of 1024 bytes from the start of the device, and it is essential
+to mounting the filesystem.  Since it is so important, backup copies of
+the superblock are stored in block groups throughout the filesystem.
+The first version of ext2 (revision 0) stores a copy at the start of
+every block group, along with backups of the group descriptor block(s).
+Because this can consume a considerable amount of space for large
+filesystems, later revisions can optionally reduce the number of backup
+copies by only putting backups in specific groups (this is the sparse
+superblock feature).  The groups chosen are 0, 1 and powers of 3, 5 and 7.
+
+The information in the superblock contains fields such as the total
+number of inodes and blocks in the filesystem and how many are free,
+how many inodes and blocks are in each block group, when the filesystem
+was mounted (and if it was cleanly unmounted), when it was modified,
+what version of the filesystem it is (see the Revisions section below)
+and which OS created it.
+
+If the filesystem is revision 1 or higher, then there are extra fields,
+such as a volume name, a unique identification number, the inode size,
+and space for optional filesystem features to store configuration info.
 
 All fields in the superblock (as in all other ext2 structures) are stored
 on the disc in little endian format, so a filesystem is portable between
@@ -101,23 +108,25 @@
 Inodes
 ------
 
-The inode (index node) is the fundamental concept in the ext2 filesystem.
+The inode (index node) is a fundamental concept in the ext2 filesystem.
 Each object in the filesystem is represented by an inode.  The inode
 structure contains pointers to the filesystem blocks which contain the
 data held in the object and all of the metadata about an object except
 its name.  The metadata about an object includes the permissions, owner,
 group, flags, size, number of blocks used, access time, change time,
 modification time, deletion time, number of links, fragments, version
-(for NFS) and ACLs.
+(for NFS) and extended attributes (EAs) and/or Access Control Lists (ACLs).
 
-There are several reserved fields which are currently unused in the inode
-structure and several which are overloaded.  One field is used for the
-directory ACL if the inode is a directory and for the top 32 bits of
-the file size if the inode is a regular file.  The translator field is
-unused under Linux, but is used by the HURD to reference the inode of
-a program which will be used to interpret this object.  The HURD also
-has larger permissions, owner and group fields, so it uses some of the
-other unused by Linux fields to store the extra bits.
+There are some reserved fields which are currently unused in the inode
+structure and several which are overloaded.  One field is reserved for the
+directory ACL if the inode is a directory and alternately for the top 32
+bits of the file size if the inode is a regular file (allowing file sizes
+larger than 2GB).  The translator field is unused under Linux, but is used
+by the HURD to reference the inode of a program which will be used to
+interpret this object.  Most of the remaining reserved fields have been
+used up for both Linux and the HURD for larger owner and group fields,
+The HURD also has a larger mode field so it uses another of the remaining
+fields to store the extra more bits.
 
 There are pointers to the first 12 blocks which contain the file's data
 in the inode.  There is a pointer to an indirect block (which contains
@@ -126,11 +135,12 @@
 trebly-indirect block (which contains pointers to doubly-indirect blocks).
 
 The flags field contains some ext2-specific flags which aren't catered
-for by the standard chmod flags.  These flags can be listed with
-lsattr and changed with the chattr command.  There are flags for secure
-deletion, undeletable, compression, synchronous updates, immutability,
-append-only, dumpable, no-atime, and btree directories.  Not all of
-these are supported yet.
+for by the standard chmod flags.  These flags can be listed with lsattr
+and changed with the chattr command, and allow specific filesystem
+behaviour on a per-file basis.  There are flags for secure deletion,
+undeletable, compression, synchronous updates, immutability, append-only,
+dumpable, no-atime, indexed directories, and data-journaling.  Not all
+of these are supported yet.
 
 Directories
 -----------
@@ -139,10 +149,19 @@
 It is a specially formatted file containing records which associate
 each name with an inode number.  Later revisions of the filesystem also
 encode the type of the object (file, directory, symlink, device, fifo,
-socket) in the directory entry for speed.  The current implementation
-of ext2 uses a linked list in directories; a planned enhancement will
-use btrees instead.  The current implementation also never shrinks
-directories once they have grown to accommodate more files.
+socket) to avoid the need to check the inode itself for this information
+(support for taking advantage of this feature does not yet exist in
+Glibc 2.2).
+
+The inode allocation code tries to assign inodes which are in the same
+block group as the directory in which they are first created.
+
+The current implementation of ext2 uses a singly-linked list to store
+the filenames in the directory; a pending enhancement uses hashing of the
+filenames to allow lookup without the need to scan the entire directory.
+
+The current implementation never removes empty directory blocks once they
+have been allocated to hold more files.
 
 Special files
 -------------
@@ -150,31 +169,23 @@
 Symbolic links are also filesystem objects with inodes.  They deserve
 special mention because the data for them is stored within the inode
 itself if the symlink is less than 60 bytes long.  It uses the fields
-which would normally be used to store the pointers to blocks to store
-the data.  This is a worthwhile optimisation to make as it does not then
-take up a block, and most symlinks are less than 60 characters long.
+which would normally be used to store the pointers to data blocks.
+This is a worthwhile optimisation as it we avoid allocating a full
+block for the symlink, and most symlinks are less than 60 characters long.
 
 Character and block special devices never have data blocks assigned to
 them.  Instead, their device number is stored in the inode, again reusing
-the fields which would be used to point to the blocks.
-
-Revisions
----------
-
-The revisioning mechanism used in ext2 is sophisticated.  The revisioning
-mechanism is not supported by version 0 (EXT2_GOOD_OLD_REV) of ext2 but
-was introduced in version 1.  There are three 32-bit fields, one for
-compatible features, one for read-only compatible features and one for
-incompatible features.
+the fields which would be used to point to the data blocks.
 
 Reserved Space
 --------------
 
 In ext2, there is a mechanism for reserving a certain number of blocks
 for a particular user (normally the super-user).  This is intended to
-allow for the system to continue functioning even if a user fills up
-all the available space.  It also keeps the filesystem from filling up
-entirely which helps combat fragmentation.
+allow for the system to continue functioning even if non-priveleged users
+fill up all the space available to them (this is independent of filesystem
+quotas).  It also keeps the filesystem from filling up entirely which
+helps combat fragmentation.
 
 Filesystem check
 ----------------
@@ -183,9 +194,66 @@
 filesystems.  The superblock of the ext2 filesystem contains several
 fields which indicate whether fsck should actually run (since checking
 the filesystem at boot can take a long time if it is large).  fsck will
-run if the filesystem was not unmounted without errors, if the maximum
-mount count has been exceeded or if the maximum time between checks has
-been exceeded.
+run if the filesystem was not cleanly unmounted, if the maximum mount
+count has been exceeded or if the maximum time between checks has been
+exceeded.
+
+Feature Compatibility
+---------------------
+
+The compatibility feature mechanism used in ext2 is sophisticated.
+It safely allows features to be added to the filesystem, without
+unnecessarily sacrificing compatibility with older versions of the
+filesystem code.  The feature compatibility mechanism is not supported by
+the original revision 0 (EXT2_GOOD_OLD_REV) of ext2, but was introduced in
+revision 1.  There are three 32-bit fields, one for compatible features
+(COMPAT), one for read-only compatible (RO_COMPAT) features and one for
+incompatible (INCOMPAT) features.
+
+These feature flags have specific meanings for the kernel as follows:
+
+A COMPAT flag indicates that a feature is present in the filesystem,
+but the on-disk format is 100% compatible with older on-disk formats, so
+a kernel which didn't know anything about this feature could read/write
+the filesystem without any chance of corrupting the filesystem (or even
+making it inconsistent).  This is essentially just a flag which says
+"this filesystem has a (hidden) feature" that the kernel or e2fsck may
+want to be aware of (more on e2fsck and feature flags later).  The ext3
+HAS_JOURNAL feature is a COMPAT flag because the ext3 journal is simply
+a regular file with data blocks in it so the kernel does not need to
+take any special notice of it if it doesn't understand ext3 journaling.
+
+An RO_COMPAT flag indicates that the on-disk format is 100% compatible
+with older on-disk formats for reading (i.e. the feature does not change
+the visible on-disk format).  However, an old kernel writing to such a
+filesystem would/could corrupt the filesystem, so this is prevented. The
+most common such feature, SPARSE_SUPER, is an RO_COMPAT feature because
+sparse groups allow file data blocks where superblock/group descriptor
+backups used to live, and ext2_free_blocks() refuses to free these blocks,
+which would leading to inconsistent bitmaps.  An old kernel would also
+get an error if it tried to free a series of blocks which crossed a group
+boundary, but this is a legitimate layout in a SPARSE_SUPER filesystem.
+
+An INCOMPAT flag indicates the on-disk format has changed in some
+way that makes it unreadable by older kernels, or would otherwise
+cause a problem if an old kernel tried to mount it.  FILETYPE is an
+INCOMPAT flag because older kernels would think a filename was longer
+than 256 characters, which would lead to corrupt directory listings.
+The COMPRESSION flag is an obvious INCOMPAT flag - if the kernel
+doesn't understand compression, you would just get garbage back from
+read() instead of it automatically decompressing your data.  The ext3
+RECOVER flag is needed to prevent a kernel which does not understand the
+ext3 journal from mounting the filesystem without replaying the journal.
+
+For e2fsck, it needs to be more strict with the handling of these
+flags than the kernel.  If it doesn't understand ANY of the COMPAT,
+RO_COMPAT, or INCOMPAT flags it will refuse to check the filesystem,
+because it has no way of verifying whether a given feature is valid
+or not.  Allowing e2fsck to succeed on a filesystem with an unknown
+feature is a false sense of security for the user.  Refusing to check
+a filesystem with unknown features is a good incentive for the user to
+update to the latest e2fsck.  This also means that anyone adding feature
+flags to ext2 also needs to update e2fsck to verify these features.
 
 Metadata
 --------
@@ -196,29 +264,98 @@
 respective fsck programs.
 
 If you're exceptionally paranoid, there are 3 ways of making metadata
-writes synchronous:
+writes synchronous on ext2:
 
-per-file if you have the source: use the O_SYNC argument to open()
-per-file if you don't have the source: use chattr +S
-per-filesystem: mount -o sync
+per-file if you have the program source: use the O_SYNC flag to open()
+per-file if you don't have the source: use "chattr +S" on the file
+per-filesystem: add the "sync" option to mount (or in /etc/fstab)
 
 the first and last are not ext2 specific but do force the metadata to
-be written synchronously.
+be written synchronously.  See also Journaling below.
+
+Limitations
+-----------
+
+There are various limits imposed by the on-disk layout of ext2.  Other
+limits are imposed by the current implementation of the kernel code.
+Many of the limits are determined at the time the filesystem is first
+created, and depend upon the block size chosen.  The ratio of inodes to
+data blocks is fixed at filesystem creation time, so the only way to
+increase the number of inodes is to increase the size of the filesystem.
+No tools currently exist which can change the ratio of inodes to blocks.
+
+Most of these limits could be overcome with slight changes in the on-disk
+format and using a compatibility flag to signal the format change (at
+the expense of some compatibility).
+
+Filesystem block size:     1kB        2kB        4kB        8kB
+
+File size limit:          16GB      256GB     2048GB     2048GB
+Filesystem size limit:  2047GB     8192GB    16384GB    32768GB
+
+There is a 2.4 kernel limit of 2048GB for a single block device, so no
+filesystem larger than that can be created at this time.  There is also
+an upper limit on the block size imposed by the page size of the kernel,
+so 8kB blocks are only allowed on Alpha systems (and other architectures
+which support larger pages).
+
+There is a "soft" upper limit of about 10-15k files in a single directory
+with the current linear linked-list directory implementation.  This limit
+stems from performance problems when creating and deleting (and also
+finding) files in such large directories.  Using a hashed directory index
+(under development) allows 100k-1M+ files in a single directory without
+performance problems (although RAM size becomes an issue at this point).
+
+The (meaningless) absolute upper limit of files in a single directory
+(imposed by the file size, the realistic limit is obviously much less)
+is over 130 trillion files.  It would be higher except there are not
+enough 4-character names to make up unique directory entries, so they
+have to be 8 character filenames, even then we are fairly close to
+running out of unique filenames.
+
+Journaling
+----------
+
+A journaling extension to the ext2 code has been developed by Stephen
+Tweedie.  It avoids the risks of metadata corruption and the need to
+wait for e2fsck to complete after a crash, without requiring a change
+to the on-disk ext2 layout.  In a nutshell, the journal is a regular
+file which stores whole metadata (and optionally data) blocks that have
+been modified, prior to writing them into the filesystem.  This means
+it is possible to add a journal to an existing ext2 filesystem without
+the need for data conversion.
+
+When changes to the filesystem (e.g. a file is renamed) they are stored in
+a transaction in the journal and can either be complete or incomplete at
+the time of a crash.  If a transaction is complete at the time of a crash
+(or in the normal case where the system does not crash), then any blocks
+in that transaction are guaranteed to represent a valid filesystem state,
+and are copied into the filesystem.  If a transaction is incomplete at
+the time of the crash, then there is no guarantee of consistency for
+the blocks in that transaction so they are discarded (which means any
+filesystem changes they represent are also lost).
+
+The ext3 code is currently (Apr 2001) available for 2.2 kernels only,
+and not yet available for 2.4 kernels.
 
 References
 ==========
 
 The kernel source	file:/usr/src/linux/fs/ext2/
-Design & Implementation	http://khg.redhat.com/HyperNews/get/fs/ext2intro.html
-Compression		http://debs.fuller.edu/e2compr/
-ACL support		ftp://tsx-11.mit.edu/pub/linux/ALPHA/ext2fs
-updated ACL work	http://aerobee.informatik.uni-bremen.de/acl_eng.html
-e2fsprogs 		ftp://tsx-11.mit.edu/pub/linux/packages/ext2fs
+e2fsprogs (e2fsck)	http://e2fsprogs.sourceforge.net/
+Design & Implementation	http://e2fsprogs.sourceforge.net/ext2intro.html
+Journaling (ext3)	ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/
+Hashed Directories	http://kernelnewbies.org/~phillips/htree/
+Filesystem Resizing	http://ext2resize.sourceforge.net/
+Extended Attributes &
+Access Control Lists	http://acl.bestbits.at/
+Compression (*)		http://www.netspace.net.au/~reiter/e2compr/
 
 Implementations for:
+Windows 95/98/NT/2000	http://uranus.it.swin.edu.au/~jn/linux/Explore2fs.htm
+Windows 95 (*)		http://www.yipton.demon.co.uk/content.html#FSDEXT2
+DOS client (*)		ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2/
 OS/2			http://perso.wanadoo.fr/matthieu.willm/ext2-os2/
-Windows 95		http://www.yipton.demon.co.uk/
-Windows NT		http://www.cyco.nl/~andreys/ext2fsnt/
-			http://uranus.it.swin.edu.au/~jn/linux/Explore2fs.htm
-DOS client		ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2/
 RISC OS client		ftp://ftp.barnet.ac.uk/pub/acorn/armlinux/iscafs/
+
+(*) no longer actively developed/supported (as of Apr 2001)
diff -u --recursive --new-file v2.4.3/linux/Documentation/filesystems/proc.txt linux/Documentation/filesystems/proc.txt
--- v2.4.3/linux/Documentation/filesystems/proc.txt	Mon Nov 27 17:47:38 2000
+++ linux/Documentation/filesystems/proc.txt	Fri Apr  6 10:42:48 2001
@@ -49,7 +49,7 @@
 the SuSE  Linux distribution. As  there is  no complete documentation  for the
 /proc file system and we've used  many freely available sources to write these
 chapters, it  seems only fair  to give the work  back to the  Linux community.
-This work is  based on the 2.2.*  kernel version and the  upcomming 2.4.*. I'm
+This work is  based on the 2.2.*  kernel version and the  upcoming 2.4.*. I'm
 afraid it's still far from complete, but we  hope it will be useful. As far as
 we know, it is the first 'all-in-one' document about the /proc file system. It
 is focused  on the Intel  x86 hardware,  so if you  are looking for  PPC, ARM,
@@ -281,7 +281,7 @@
 
 ERR is incremented in the case of errors in the IO-APIC bus (the bus that
 connects the CPUs in a SMP system. This means that an error has been detected,
-the IO-APIC automatically retry the transmision, so it should not be a big
+the IO-APIC automatically retry the transmission, so it should not be a big
 problem, but you should read the SMP-FAQ.
 
 In this context it could be interesting to note the new irq directory in 2.4.
diff -u --recursive --new-file v2.4.3/linux/Documentation/filesystems/vfat.txt linux/Documentation/filesystems/vfat.txt
--- v2.4.3/linux/Documentation/filesystems/vfat.txt	Tue Dec 21 14:28:39 1999
+++ linux/Documentation/filesystems/vfat.txt	Wed Apr 11 19:02:27 2001
@@ -48,6 +48,9 @@
                  r: relaxed, case insensitive
                  n: normal, default setting, currently case insensitive
 
+nocase        -- Returning with having the 8.3 format alias kept in
+                 the disk. Default, return lowercase letter.
+
 <bool>: 0,1,yes,no,true,false
 
 TODO
diff -u --recursive --new-file v2.4.3/linux/Documentation/i386/boot.txt linux/Documentation/i386/boot.txt
--- v2.4.3/linux/Documentation/i386/boot.txt	Thu Jul 27 16:52:08 2000
+++ linux/Documentation/i386/boot.txt	Wed Apr 11 18:50:25 2001
@@ -146,9 +146,16 @@
 filled out, however:
 
   type_of_loader:
-	If your boot loader has an identifier assigned in
-	arch/i386/boot/setup.S, enter that value.  Otherwise, enter
-	0xFF here.
+	If your boot loader has an assigned id (see table below), enter
+	0xTV here, where T is an identifier for the boot loader and V is
+	a version number.  Otherwise, enter 0xFF here.
+
+	Assigned boot loader ids:
+	0  LILO
+	1  Loadlin
+	2  bootsect-loader
+	3  SYSLINUX
+	4  EtherBoot
 
   loadflags, heap_end_ptr:
 	If the protocol version is 2.01 or higher, enter the
diff -u --recursive --new-file v2.4.3/linux/Documentation/i810_rng.txt linux/Documentation/i810_rng.txt
--- v2.4.3/linux/Documentation/i810_rng.txt	Sun Mar 25 18:24:31 2001
+++ linux/Documentation/i810_rng.txt	Thu Apr 19 09:34:05 2001
@@ -70,6 +70,9 @@
 
 Change history:
 
+	Version 0.9.6:
+	* Internal driver cleanups, prep for 1.0.0 release.
+
 	Version 0.9.5:
 	* Rip out entropy injection via timer.  It never ever worked,
 	  and a better solution (rngd) is now available.
diff -u --recursive --new-file v2.4.3/linux/Documentation/isapnp.txt linux/Documentation/isapnp.txt
--- v2.4.3/linux/Documentation/isapnp.txt	Mon Oct  9 17:53:05 2000
+++ linux/Documentation/isapnp.txt	Wed Apr 18 11:49:11 2001
@@ -7,14 +7,14 @@
 Read commands:
 --------------
 
-No comment..
+No comment.
 
 Write commands:
 ---------------
 
-With the write interface you can simply activate or modify the configuration
-for ISA Plug & Play devices. It is mainly useable for drivers which has not
-use the ISA Plug & Play kernel support yet.
+With the write interface you can activate or modify the configuration of
+ISA Plug & Play devices.  It is mainly useful for drivers which have not
+been rewritten to use the ISA Plug & Play kernel support yet.
 
 card <idx> <vendor>	- select PnP device by vendor identification
 csn <CSN>		- select PnP device by CSN
@@ -33,8 +33,8 @@
 Explanation:
 	- variable <idx> begins with zero
 	- variable <CSN> begins with one
-	- <vendor> is in format 'PNP0000'
-	- <logdev> is in format 'PNP0000'
+	- <vendor> is in the standard format 'ABC1234'
+	- <logdev> is in the standard format 'ABC1234'
 
 Example:
 
@@ -58,38 +58,38 @@
 Information for developers
 ==========================
 
-Finding appropriate device
---------------------------
+Finding a device
+----------------
 
 extern struct pci_bus *isapnp_find_card(unsigned short vendor,
                                         unsigned short device,
                                         struct pci_bus *from);
 
-This function finds a ISA PnP card. For the vendor device should
-be used ISAPNP_VENDOR(a,b,c) where a,b,c are characters or integers.
-For the device number should be used ISAPNP_DEVICE(x) macro where x is
-integer value. Both vendor and device numbers can be taken from contents
-of the /proc/isapnp file.
+This function finds an ISA PnP card.  For the vendor argument, the
+ISAPNP_VENDOR(a,b,c) macro should be used, where a,b,c are characters or
+integers.  For the device argument the ISAPNP_DEVICE(x) macro should be
+used, where x is an integer value.  Both vendor and device arguments
+can be taken from contents of the /proc/isapnp file.
 
 extern struct pci_dev *isapnp_find_dev(struct pci_bus *card,
                                        unsigned short vendor,
                                        unsigned short function,
                                        struct pci_dev *from);
 
-This function finds the ISA PnP device. If card is NULL, then
-the global search mode is used (all devices are used for the searching).
-Otherwise only devices which belongs to the specified card are verified.
-For the function number can be used ISAPNP_FUNCTION(x) macro which works
-similarly as the ISAPNP_DEVICE(x) macro.
+This function finds an ISA PnP device. If card is NULL, then the global
+search mode is used (all devices are used for the searching).  Otherwise
+only devices which belong to the specified card are checked.  For the
+function number the ISAPNP_FUNCTION(x) macro can be used; it works
+similarly to the ISAPNP_DEVICE(x) macro.
 
 extern int isapnp_probe_cards(const struct isapnp_card_id *ids,
-			      int (*probe)(struct pci_bus *card,
-					   const struct isapnp_card_id *id));
+                              int (*probe)(struct pci_bus *card,
+                              const struct isapnp_card_id *id));
 
 
-This function is a helper for drivers which requires to use more than
-one device from an ISA PnP card. For each cards is called the probe
-callback with appropriate information.
+This function is a helper for drivers which need to use more than
+one device from an ISA PnP card.  The probe callback is called with
+appropriate arguments for each card.
 
 Example for ids parameter initialization:
 
@@ -109,13 +109,13 @@
 ISAPNP_CARD_TABLE(card_ids);
 
 extern int isapnp_probe_devs(const struct isapnp_device_id *ids,
-			     int (*probe)(struct pci_bus *card,
-					  const struct isapnp_device_id *id));
+                             int (*probe)(struct pci_bus *card,
+                             const struct isapnp_device_id *id));
 
 
-This function is a helper for drivers which requires to use one
-device from an ISA PnP card. For each matched devices is called the probe
-callback with appropriate information.
+This function is a helper for drivers which need to use one
+device from an ISA PnP card.  The probe callback is called with
+appropriate arguments for each matched device.
 
 Example for ids parameter initialization:
 
@@ -129,25 +129,25 @@
 ISA PnP configuration
 =====================
 
-There are two ways how can be ISA PnP interface used.
+There are two ways in which the ISA PnP interface can be used.
 
-First way is lowlevel
----------------------
+First way: low-level
+--------------------
 
-All ISA PNP configuration registers are accessible via lowlevel
+All ISA PNP configuration registers are accessible via the low-level
 isapnp_(read|write)_(byte|word|dword) functions.
 
 The function isapnp_cfg_begin() must be called before any lowlevel function.
 The function isapnp_cfg_end() must be always called after configuration
 otherwise the access to the ISA PnP configuration functions will be blocked.
 
-Second way is auto-configuration
---------------------------------
+Second way: auto-configuration
+------------------------------
 
-This feature gives to the driver the real power of the ISA PnP code.
-Function dev->prepare() initializes the resource members in the device
-structure. This structure contains all resources set to auto configuration
-values after the initialization. The device driver may modify some resources
+This feature gives to the driver the real power of the ISA PnP driver.
+The function dev->prepare() initializes the resource members in the device
+structure.  This structure contains all resources set to auto configuration
+values after the initialization.  The device driver may modify some resources
 to skip the auto configuration for a given resource.
 
 Once the device structure contains all requested resource values, the function
@@ -155,12 +155,12 @@
 with the auto configuration value.
 
 Function dev->activate() does:
-	- resources with the auto configuration value are configured
-	- the auto configuration is created using ISA PnP resource map
-	- the function writes configuration to ISA PnP configuration registers
-	- the function returns to the caller actual used resources
+   - resources with the auto configuration value are configured
+   - the auto configuration is created using ISA PnP resource map
+   - the function writes configuration to ISA PnP configuration registers
+   - the function returns to the caller actual used resources
 
-When the device driver is removing, function dev->deactivate() has to be
+When the device driver is removed, function dev->deactivate() has to be
 called to free all assigned resources.
 
 Example (game port initialization)
diff -u --recursive --new-file v2.4.3/linux/Documentation/joystick-api.txt linux/Documentation/joystick-api.txt
--- v2.4.3/linux/Documentation/joystick-api.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/joystick-api.txt	Fri Apr  6 10:42:48 2001
@@ -114,7 +114,7 @@
 ~~~~~~~~~~~~~~~~~
 
 The time an event was generated is stored in ``js_event.time''. It's a time
-in miliseconds since ... well, since sometime in the past.  This eases the
+in milliseconds since ... well, since sometime in the past.  This eases the
 task of detecting double clicks, figuring out if movement of axis and button
 presses happened at the same time, and similar.
 
diff -u --recursive --new-file v2.4.3/linux/Documentation/kernel-docs.txt linux/Documentation/kernel-docs.txt
--- v2.4.3/linux/Documentation/kernel-docs.txt	Wed Aug 23 09:33:09 2000
+++ linux/Documentation/kernel-docs.txt	Fri Apr  6 10:42:48 2001
@@ -608,7 +608,7 @@
        produced during the week. Published every Thursday.
        
      * Name: "Kernel Traffic"
-       URL: http://kt.linuxcare.com
+       URL: http://kt.zork.net
        Keywords: linux-kernel mailing list, weekly kernel news.
        Description: Weekly newsletter covering the most relevant
        discussions of the linux-kernel mailing list.
diff -u --recursive --new-file v2.4.3/linux/Documentation/kernel-parameters.txt linux/Documentation/kernel-parameters.txt
--- v2.4.3/linux/Documentation/kernel-parameters.txt	Fri Mar  2 11:02:15 2001
+++ linux/Documentation/kernel-parameters.txt	Wed Apr 18 11:49:11 2001
@@ -22,6 +22,7 @@
 	HW	Appropriate hardware is enabled.
 	IA-32	IA-32 aka i386 architecture is enabled.
 	IA-64	IA-64 architecture is enabled.
+	ISAPNP  ISA PnP code is enabled.
 	ISDN	Appropriate ISDN support is enabled.
 	JOY 	Appropriate joystick support is enabled.
 	LP	Printer support is enabled.
@@ -246,6 +247,18 @@
 
 	ip=		[PNP]
 
+	isapnp=		[ISAPNP] Specify RDP, reset, pci_scan and verbosity.
+
+	isapnp_reserve_irq= [ISAPNP] Exclude IRQs for the autoconfiguration.
+
+	isapnp_reserve_dma= [ISAPNP] Exclude DMAs for the autoconfiguration.
+
+	isapnp_reserve_io= [ISAPNP] Exclude I/O ports for the autoconfiguration.
+				    Ranges are in pairs (I/O port base and size).
+
+	isapnp_reserve_mem= [ISAPNP] Exclude memory regions for the autoconfiguration.
+				     Ranges are in pairs (memory base and size).
+
 	isp16=		[HW,CD]
 
 	iucv=		[HW,NET] 
@@ -361,6 +374,8 @@
 	nohlt		[BUGS=ARM]
  
 	no-hlt		[BUGS=ix86]
+
+	noisapnp	[ISAPNP] Disables ISA PnP code.
 
 	noinitrd	[RAM] Tells the kernel not to load any configured
 			initial RAM disk.
diff -u --recursive --new-file v2.4.3/linux/Documentation/mips/GT64120.README linux/Documentation/mips/GT64120.README
--- v2.4.3/linux/Documentation/mips/GT64120.README	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/mips/GT64120.README	Fri Apr 20 16:23:12 2001
@@ -0,0 +1,65 @@
+README for arch/mips/gt64120 directory and subdirectories
+
+Jun Sun, jsun@mvista.com or jsun@junsun.net
+01/27, 2001
+
+MOTIVATION
+----------
+
+Many MIPS boards share the same system controller (or CPU companian chip),
+such as GT-64120.  It is highly desirable to let these boards share
+the same controller code instead of duplicating them.
+
+This directory is meant to hold all MIPS boards that use GT-64120 or GT-64120A.
+
+
+HOW TO ADD A BOARD
+------------------
+ 
+. Create a subdirectory include/asm/gt64120/<board>.  
+
+. Create a file called gt64120_dep.h under that directory.
+
+. Modify include/asm/gt64120/gt64120.h file to include the new gt64120_dep.h
+  based on config options.  The board-dep section is at the end of 
+  include/asm/gt64120/gt64120.h file. There you can find all required
+  definitions include/asm/gt64120/<board>/gt64120_dep.h file must supply.
+
+. Create a subdirectory arch/mips/gt64120/<board> directory to hold
+  board specific routines.
+
+. The GT-64120 common code is supplied under arch/mips/gt64120/common directory.
+  It includes:
+	1) arch/mips/gt64120/pci.c -
+		common PCI routine, include the top-level pcibios_init()
+	2) arch/mips/gt64120/irq.c -
+		common IRQ routine, include the top-level do_IRQ() 
+	   [This part really belongs to arch/mips/kernel. jsun]
+ 	3) arch/mips/gt64120/gt_irq.c -
+		common IRQ routines for GT-64120 chip.  Currently it only handles
+	 	the timer interrupt.
+
+. Board-specific routines are supplied under arch/mips/gt64120/<board> dir.
+	1) arch/mips/gt64120/<board>/pci.c - it provides bus fixup routine
+	2) arch/mips/gt64120/<board>/irq.c - it provides enable/disable irqs
+		and board irq setup routine (irq_setup)
+	3) arch/mips/gt64120/<board>/int-handler.S -
+		The first-level interrupt dispatching routine.
+	4) a bunch of other "normal" stuff (setup, prom, dbg_io, reset, etc)
+
+. Follow other "normal" procedure to modify configuration files, etc.
+
+
+TO-DO LIST
+----------
+
+. Expand arch/mips/gt64120/gt_irq.c to handle all GT-64120 interrupts.
+  We probably need to introduce GT_IRQ_BASE  in board-dep header file,
+  which is used the starting irq_nr for all GT irqs.
+
+  A function, gt64120_handle_irq(), will be added so that the first-level
+  irq dispatcher will call this function if it detects an interrupt
+  from GT-64120.
+
+. More support for GT-64120 PCI features (2nd PCI bus, perhaps)
+
diff -u --recursive --new-file v2.4.3/linux/Documentation/mips/time.README linux/Documentation/mips/time.README
--- v2.4.3/linux/Documentation/mips/time.README	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/mips/time.README	Fri Apr 20 16:23:12 2001
@@ -0,0 +1,161 @@
+README for MIPS time services
+
+Jun Sun
+jsun@mvista.com or jsun@junsun.net
+
+
+ABOUT
+-----
+This file describes the new arch/mips/kernel/time.c, related files and the 
+services they provide. 
+
+If you are short in patience and just want to know how to use time.c for a 
+new board or convert an existing board, go to the last section.
+
+
+FILES, COMPATABILITY AND CONFIGS
+---------------------------------
+
+The old arch/mips/kernel/time.c is renamed to old-time.c.
+
+A new time.c is put there, together with include/asm-mips/time.h.
+
+Two configs variables are introduced, CONFIG_OLD_TIME_C and CONFIG_NEW_TIME_C.
+So we allow boards using 
+
+	1) old time.c (CONFIG_OLD_TIME_C)
+	2) new time.c (CONFIG_NEW_TIME_C)
+	3) neither (their own private time.c)
+
+However, it is expected every board will move to the new time.c in the near
+future.
+
+
+WHAT THE NEW CODE PROVIDES?
+--------------------------- 
+
+The new time code provide the following services:
+
+  a) Implements functions required by Linux common code:
+	time_init
+	do_gettimeofday
+	do_settimeofday
+
+  b) provides an abstraction of RTC and null RTC implementation as default.
+	extern unsigned long (*rtc_get_time)(void);
+	extern int (*rtc_set_time)(unsigned long);
+
+  c) a set of gettimeoffset functions for different CPUs and different
+     needs.
+
+  d) high-level and low-level timer interrupt routines where the timer 
+     interrupt source  may or may not be the CPU timer.  The high-level 
+     routine is dispatched through do_IRQ() while the low-level is 
+     dispatched in assemably code (usually int-handler.S)
+
+
+WHAT THE NEW CODE REQUIRES?
+---------------------------
+
+For the new code to work properly, each board implementation needs to supply
+the following functions or values:
+
+  a) board_time_init - a function pointer.  Invoked at the beginnig of
+     time_init().  It is optional.
+	1. (optional) set up RTC routines
+	2. (optional) calibrate and set the mips_counter_frequency
+
+  b) board_timer_setup - a function pointer.  Invoked at the end of time_init()
+	1. (optional) over-ride any decisions made in time_init()
+	2. set up the irqaction for timer interrupt.
+	3. enable the timer interrupt
+
+  c) (optional) board-specific RTC routines.
+
+  d) (optional) mips_counter_frequency - It must be definied if the board
+     is using CPU counter for timer interrupt or it is using fixed rate
+     gettimeoffset().
+
+
+PORTING GUIDE
+-------------
+
+Step 1: decide how you like to implement the time services.
+
+  a) does this board have a RTC?  If yes, implement the two RTC funcs.
+
+  b) does the CPU have counter/compare registers? 
+
+     If the answer is no, you need a timer to provide the timer interrupt
+     at 100 HZ speed.
+
+     You cannot use the fast gettimeoffset functions, i.e.,
+
+	unsigned long fixed_rate_gettimeoffset(void);
+	unsigned long calibrate_div32_gettimeoffset(void);
+	unsigned long calibrate_div64_gettimeoffset(void);
+
+    You can use null_gettimeoffset() will gives the same time resolution as
+    jiffy.  Or you can implement your own gettimeoffset (probably based on 
+    some ad hoc hardware on your machine.)
+
+  c) The following sub steps assume your CPU has counter register.
+     Do you plan to use the CPU counter register as the timer interrupt
+     or use an exnternal timer?
+
+     In order to CPU counter register as the timer interrupt source, you must
+     know the counter speed (mips_counter_frequency).  It is usually the
+     same as the CPU speed (Or it is ALWAYS the same?)
+
+  d) decide on whether you want to use high-level or low-level timer
+     interrupt routines.  The low-level one is presumably faster, but should
+     not make too mcuh difference.
+
+
+Step 2:  the machine setup() function
+
+  If you supply board_time_init(), set the function poointer.
+
+  Set the function pointer board_timer_setup() (mandatory)
+
+
+Step 3: implement rtc routines, board_time_init() and board_timer_setup()
+  if needed.
+
+  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)
+
+  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
+
+
+  If the RTC chip is a common chip, I suggest the routines are put under
+  arch/mips/libs.  For example, for DS1386 chip, one would create
+  rtc-ds1386.c under arch/mips/lib directory.  Add the following line to
+  the arch/mips/lib/Makefile:
+
+	obj-$(CONFIG_DDB5476) += rtc-ds1386.o
+
+Step 4: if you are using low-level timer interrupt, change your interrupt
+  dispathcing code to check for timer interrupt and jump to 
+  ll_timer_interrupt() directly  if one is detected.
+
+Step 5: Modify arch/mips/config.in and add CONFIG_NEW_TIME_C to your machine.
+  Modify the appropriate defconfig if applicable.
+
+Final notes: 
+
+For some tricky cases, you may need to add your own wrapper functions 
+for some of the functions in time.c.  
+
+For example, you may define your own timer interrupt routine, which does
+its own processing and in turn calls timer_interrupt().
+
+You can also over-ride any of the built-in functions (gettimeoffset,
+RTC routines and/or timer interrupt routine).
+
diff -u --recursive --new-file v2.4.3/linux/Documentation/mtrr.txt linux/Documentation/mtrr.txt
--- v2.4.3/linux/Documentation/mtrr.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/mtrr.txt	Wed Apr 11 19:02:27 2001
@@ -16,10 +16,13 @@
   these, the ARRs are used to emulate the MTRRs.
 
   The AMD K6-2 (stepping 8 and above) and K6-3 processors have two
-  MTRRs. These are supported.
+  MTRRs. These are supported.  The AMD Athlon family provide 8 Intel
+  style MTRRs.
   
   The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These
   are supported.
+
+  The VIA Cyrix III and VIA C3 CPUs offer 8 Intel style MTRRs.
 
   The CONFIG_MTRR option creates a /proc/mtrr file which may be used
   to manipulate your MTRRs. Typically the X server should use
diff -u --recursive --new-file v2.4.3/linux/Documentation/networking/8139too.txt linux/Documentation/networking/8139too.txt
--- v2.4.3/linux/Documentation/networking/8139too.txt	Sun Mar 25 18:24:31 2001
+++ linux/Documentation/networking/8139too.txt	Thu Apr 19 09:32:48 2001
@@ -185,6 +185,24 @@
 Change History
 --------------
 
+Version 0.9.16 - April 14, 2001
+
+* Complete MMIO audit, disable read-after-every-write
+* Update Rx interrupt handling
+* Enable Early Rx thresholds, highly recommended to reduce
+  Rx FIFO overflow
+* Make 8129 support conditional
+* Support for new 2.4.3 kernel APIs
+* More correct PIO/MMIO PCI BAR region size checking
+* Add check for totally dead/missing hardware
+* Disable media timer code to "set full duplex"
+* s/spin_lock_irq/spin_lock_irqsave/
+* Only set AcceptMulticast if more than one mc address
+* Only set rx_mode if changed, in set_rx_mode
+* Only suspend/resume if interface is up
+* Always print out version upon module load, even if no devices found
+
+
 Version 0.9.15 - February 20, 2001
 
 * Call pci_enable_device to wake up/assign resource to device,
diff -u --recursive --new-file v2.4.3/linux/Documentation/networking/TODO linux/Documentation/networking/TODO
--- v2.4.3/linux/Documentation/networking/TODO	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/TODO	Thu Apr 19 13:43:40 2001
@@ -0,0 +1,25 @@
+To-do items for network drivers
+-------------------------------
+
+* Move ethernet crc routine to generic code
+
+* (for 2.5) Integrate Jamal Hadi Salim's netdev Rx polling API change
+
+* Audit all net drivers to make sure magic packet / wake-on-lan /
+  similar features are disabled in the driver by default.
+
+* Audit all net drivers to make sure the module always prints out a
+  version string when loaded as a module, but only prints a version
+  string when built into the kernel if a device is detected.
+
+* 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.
+
diff -u --recursive --new-file v2.4.3/linux/Documentation/networking/comx.txt linux/Documentation/networking/comx.txt
--- v2.4.3/linux/Documentation/networking/comx.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/networking/comx.txt	Fri Apr  6 10:42:48 2001
@@ -162,7 +162,7 @@
 some restricions in order to be able to use non-async lines too.
 If configured, this driver can use Van Jacobson TCP header compression (you'll
 need the slhc.o module for this).
-Additionaly to use this protocol, enable async ppp in your kernel config, and
+Additionally to use this protocol, enable async ppp in your kernel config, and
 create the comx device special files in /dev. They're character special files
 with major 88, and their names must be the same as their network interface
 counterparts (i.e /dev/comx0 with minor 0 corresponds interface comx0 and so
diff -u --recursive --new-file v2.4.3/linux/Documentation/networking/olympic.txt linux/Documentation/networking/olympic.txt
--- v2.4.3/linux/Documentation/networking/olympic.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/networking/olympic.txt	Wed Apr 18 11:39:21 2001
@@ -3,18 +3,21 @@
 
 Release 0.2.0 - Release    
 	June 8th 1999 Peter De Schrijver & Mike Phillips
-
+Release 0.9.C - Release
+	April 18th 2001 Mike Phillips
 
 Thanks:
 Erik De Cock, Adrian Bridgett and Frank Fiene for their 
-patience and testing.  
-Paul Norton without whose tr.c code we would have had
-a lot more work to do.
+patience and testing.
+Donald Champion for the cardbus support
+Kyle Lucke for the dma api changes.   
+Jonathon Bitner for hardware support. 
+Everybody on linux-tr for their continued support.  
  
 Options:
 
-The driver accepts three options: ringspeed, pkt_buf_sz, and  
-message_level.
+The driver accepts four options: ringspeed, pkt_buf_sz,  
+message_level and network_monitor.
 
 These options can be specified differently for each card found. 
 
@@ -40,6 +43,17 @@
 value will display all soft messages as well.  NB This does not turn 
 debugging messages on, that must be done by modified the source code.
 
+network_monitor: Any non-zero value will provide a quasi network monitoring 
+mode.  All unexpected MAC frames (beaconing etc.) will be received
+by the driver and the source and destination addresses printed. 
+Also an entry will be added in  /proc/net called olympic_tr%d, where tr%d
+is the registered device name, i.e tr0, tr1, etc. This displays low
+level information about the configuration of the ring and the adapter.
+This feature has been designed for network administrators to assist in 
+the diagnosis of network / ring problems. (This used to OLYMPIC_NETWORK_MONITOR,
+but has now changed to allow each adapter to be configured differently and
+to alleviate the necessity to re-compile olympic to turn the option on).
+
 Multi-card:
 
 The driver will detect multiple cards and will work with shared interrupts,
@@ -60,16 +74,6 @@
 building routers, gateway's etc, you could start to use a lot of memory
 real fast.
 
-Network Monitor Mode:
-
-By modifying the #define OLYMPIC_NETWORK_MONITOR from 0 to 1 in the 
-source code the driver will implement a quasi network monitoring 
-mode.  All unexpected MAC frames (beaconing etc.) will be received
-by the driver and the source and destination addresses printed. 
-Also an entry will be added in  /proc/net called olympic_tr. This 
-displays low level information about the configuration of the ring and
-the adapter. This feature has been designed for network administrators
-to assist in the diagnosis of network / ring problems.
 
 6/8/99 Peter De Schrijver and Mike Phillips
 
diff -u --recursive --new-file v2.4.3/linux/Documentation/networking/tuntap.txt linux/Documentation/networking/tuntap.txt
--- v2.4.3/linux/Documentation/networking/tuntap.txt	Fri Sep 22 15:19:30 2000
+++ linux/Documentation/networking/tuntap.txt	Wed Apr 25 14:59:56 2001
@@ -37,7 +37,7 @@
 	alias char-major-10-200 tun
      
      Run:
-        modprobe -a 
+        depmod -a 
 
      Driver will be automatically loaded when application access /dev/net/tun.
 
diff -u --recursive --new-file v2.4.3/linux/Documentation/networking/wan-router.txt linux/Documentation/networking/wan-router.txt
--- v2.4.3/linux/Documentation/networking/wan-router.txt	Fri Jul 28 12:50:52 2000
+++ linux/Documentation/networking/wan-router.txt	Thu Apr 12 12:11:39 2001
@@ -1,27 +1,12 @@
 ------------------------------------------------------------------------------
-WAN Router for Linux Operating System
+Linux WAN Router Utilities Package
 ------------------------------------------------------------------------------
-Version 2.1.1 - Nov 08, 1999
-Version 2.0.8 - Nov 02, 1999
-Version 2.0.7 - Aug 26, 1999
-Version 2.0.6 - Aug 17, 1999
-Version 2.0.5 - Aug 12, 1999
-Version 2.0.4 - Nov 26, 1998
-Version 2.0.3 - Aug 25, 1998
-Version 2.0.2 - Dec 09, 1997
-Version 2.0.1 - Nov 28, 1997
-Version 2.0.0 - Nov 06, 1997
-Version 1.0.3 - June 3, 1997
-Version 1.0.1 - January 30, 1997
+Version 2.2.1 
+Mar 28, 2001
 Author: Nenad Corbic <ncorbic@sangoma.com>
-Copyright (c) 1995-1999 Sangoma Technologies Inc.
+Copyright (c) 1995-2001 Sangoma Technologies Inc.
 ------------------------------------------------------------------------------
 
-
-WARNING:  This Version of WANPIPE supports only the S508 and S508/FT1 cards.  
-IF YOU OWN A S502E OR A S508 CARD THEN PLEASE CONTACT SANGOMA TECHNOLOGIES FOR 
-AN UPGRADE.  ONLY THE BiSYNC STREAMING CODE IS SUPPORTED ON S502E/S503 cards. 
-
 INTRODUCTION
 
 Wide Area Networks (WANs) are used to interconnect Local Area Networks (LANs)
@@ -41,7 +26,7 @@
 Unix-like operating system anyway). With a number of relatively inexpensive WAN
 interface cards available on the market, a perfectly usable router can be
 built for less than half a price of an external router.  Yet a Linux box
-acting as a router can still be used for other purposes, such as firewalling,
+acting as a router can still be used for other purposes, such as fire-walling,
 running FTP, WWW or DNS server, etc.
 
 This kernel module introduces the notion of a WAN Link Driver (WLD) to Linux
@@ -87,15 +72,28 @@
 To ba able to use the Linux WAN Router you will also need a WAN Tools package
 available from
 
-	ftp.sangoma.com/pub/linux/vX.Y.Z/wantools-X.Y.Z.tgz
-			or
-	ftp.sangoma.com/pub/linux/vX.Y.Z/wanpipe-X.Y.Z.tgz
+	ftp.sangoma.com/pub/linux/current_wanpipe/wanpipe-X.Y.Z.tgz
+
+where vX.Y.Z represent the wanpipe version number.
+
+For technical questions and/or comments please e-mail to ncorbic@sangoma.com.
+For general inquiries please contact Sangoma Technologies Inc. by
 
-where vX.Y.Z represent the Linux kernel version number.
+	Hotline:	1-800-388-2475	(USA and Canada, toll free)
+	Phone:		(905) 474-1990  ext: 106
+	Fax:		(905) 474-9223
+	E-mail:		dm@sangoma.com	(David Mandelstam)
+	WWW:		http://www.sangoma.com
 
-For technical questions and/or comments regarding this product please e-mail
-to jaspreet@sangoma.com or dm@sangoma.com.
 
+INSTALLATION
+
+Please read the WanpipeForLinux.pdf manual on how to 
+install the WANPIPE tools and drivers properly. 
+
+
+After installing wanpipe package: /usr/local/wanrouter/doc. 
+On the ftp.sangoma.com : /linux/current_wanpipe/doc
 
 
 COPYRIGHT AND LICENSING INFORMATION
@@ -114,120 +112,511 @@
 
 
 
-ACKNOWLEDGMENTS
+ACKNOWLEDGEMENTS
 
 This product is based on the WANPIPE(tm) Multiprotocol WAN Router developed
-by Sangoma Technologies Inc. for Linux 1.2.x.  Release of Linux 2.0 in summer
-1996 commanded adequate changes to the WANPIPE code to take full advantage of
-new Linux features.  Instead of continuing developing proprietary interface
-specific to Sangoma WAN cards, we decided to put all hardware-independent code
-into a separate module and define two levels of interfaces - one for user-
-level applications and another for kernel-level WAN drivers.
+by Sangoma Technologies Inc. for Linux 2.0.x and 2.2.x.  Success of the WANPIPE
+together with the next major release of Linux kernel in summer 1996 commanded
+adequate changes to the WANPIPE code to take full advantage of new Linux
+features.
+
+Instead of continuing developing proprietary interface tied to Sangoma WAN
+cards, we decided to separate all hardware-independent code into a separate
+module and defined two levels of interfaces - one for user-level applications
+and another for kernel-level WAN drivers.  WANPIPE is now implemented as a
+WAN driver compliant with the WAN Link Driver interface.  Also a general
+purpose WAN configuration utility and a set of shell scripts was developed to 
+support WAN router at the user level.
 
 Many useful ideas concerning hardware-independent interface implementation
 were given by Mike McLagan <mike.mclagan@linux.org> and his implementation
 of the Frame Relay router and drivers for Sangoma cards (dlci/sdla).
 
+With the new implementation of the APIs being incorporated into the WANPIPE,
+a special thank goes to Alan Cox in providing insight into BSD sockets.
+
 Special thanks to all the WANPIPE users who performed field-testing, reported
 bugs and made valuable comments and suggestions that help us to improve this
 product.
 
 
 
+NEW IN THIS RELEASE
+
+	o Updated the WANCFG utility
+		Calls the pppconfig to configure the PPPD
+		for async connections.
+
+	o Added the PPPCONFIG utility
+		Used to configure the PPPD dameon for the
+		WANPIPE Async PPP and standard serial port.
+		The wancfg calls the pppconfig to configure
+		the pppd.
+
+	o Fixed the PCI autodetect feature.  
+		The SLOT 0 was used as an autodetect option
+		however, some high end PC's slot numbers start
+		from 0. 
+
+	o This release has been tested with the new backupd
+	  daemon release.
+	
+
+PRODUCT COMPONENTS AND RELATED FILES
+
+/etc: (or user defined)
+	wanpipe1.conf	default router configuration file
+
+/lib/modules/X.Y.Z/misc:
+	wanrouter.o	router kernel loadable module
+	af_wanpipe.o	wanpipe api socket module
+
+/lib/modules/X.Y.Z/net:
+	sdladrv.o	Sangoma SDLA support module
+	wanpipe.o	Sangoma WANPIPE(tm) driver module
+
+/proc/net/wanrouter
+	Config		reads current router configuration
+	Status		reads current router status
+	{name}		reads WAN driver statistics
+
+/usr/sbin:
+	wanrouter	wanrouter start-up script
+	wanconfig	wanrouter configuration utility
+	sdladump	WANPIPE adapter memory dump utility
+        fpipemon        Monitor for Frame Relay
+        cpipemon        Monitor for Cisco HDLC
+	ppipemon 	Monitor for PPP
+	xpipemon 	Monitor for X25
+	wpkbdmon        WANPIPE keyboard led monitor/debugger
+
+/usr/local/wanrouter:
+	README		this file
+	COPYING		GNU General Public License
+	Setup		installation script
+	Filelist	distribution definition file
+	wanrouter.rc	meta-configuration file 
+			(used by the Setup and wanrouter script)
+
+/usr/local/wanrouter/doc:
+	wanpipeForLinux.pdf 	WAN Router User's Manual
+
+/usr/local/wanrouter/patches:
+	wanrouter-v2213.gz  	patch for Linux kernels 2.2.11 up to 2.2.13.
+	wanrouter-v2214.gz	patch for Linux kernel 2.2.14. 
+	wanrouter-v2215.gz	patch for Linux kernels 2.2.15 to 2.2.17.
+	wanrouter-v2218.gz	patch for Linux kernels 2.2.18 and up.
+	wanrouter-v240.gz	patch for Linux kernel 2.4.0.  
+	wanrouter-v242.gz	patch for Linux kernel 2.4.2 and up.
+	wanrouter-v2034.gz	patch for Linux kernel 2.0.34
+	wanrouter-v2036.gz 	patch for Linux kernel 2.0.36 and up. 
+
+/usr/local/wanrouter/patches/kdrivers:
+	Sources of the latest WANPIPE device drivers.
+	These are used to UPGRADE the linux kernel to the newest
+	version if the kernel source has already been pathced with
+	WANPIPE drivers.
+
+/usr/local/wanrouter/samples:
+	interface	sample interface configuration file
+	wanpipe1.cpri 	CHDLC primary port
+     	wanpipe2.csec 	CHDLC secondary port
+     	wanpipe1.fr   	Frame Relay protocol
+     	wanpipe1.ppp  	PPP protocol ) 
+	wanpipe1.asy	CHDLC ASYNC protocol
+	wanpipe1.x25	X25 protocol
+	wanpipe1.stty	Sync TTY driver (Used by Kernel PPPD daemon)
+	wanpipe1.atty	Async TTY driver (Used by Kernel PPPD daemon)
+	wanrouter.rc	sample meta-configuration file
+
+/usr/local/wanrouter/util:
+	*		wan-tools utilities source code
+
+/usr/local/wanrouter/api/x25:
+	*		x25 api sample programs.
+/usr/local/wanrouter/api/chdlc:
+	*		chdlc api sample programs.
+/usr/local/wanrouter/api/fr:
+	*		fr api sample programs.
+/usr/local/wanrouter/config/wancfg:
+	wancfg		WANPIPE GUI configuration program.
+                        Creates wanpipe#.conf files. 
+/usr/local/wanrouter/config/cfgft1:
+	cfgft1		GUI CSU/DSU configuration program.
+
+/usr/include/linux:
+	wanrouter.h	router API definitions
+	wanpipe.h	WANPIPE API definitions
+	sdladrv.h	SDLA support module API definitions
+	sdlasfm.h	SDLA firmware module definitions
+	if_wanpipe.h	WANPIPE Socket definitions
+	if_wanpipe_common.h	WANPIPE Socket/Driver common definitions.
+	sdlapci.h	WANPIPE PCI definitions
+	
+
+/usr/src/linux/net/wanrouter:
+	*		wanrouter source code
+
+/var/log:
+	wanrouter	wanrouter start-up log (created by the Setup script)
+
+/var/lock:  (or /var/lock/subsys for RedHat)
+	wanrouter	wanrouter lock file (created by the Setup script)
+
+/usr/local/wanrouter/firmware:
+	fr514.sfm	Frame relay firmware for Sangoma S508/S514 card
+	cdual514.sfm	Dual Port Cisco HDLC firmware for Sangoma S508/S514 card
+	ppp514.sfm      PPP Firmware for Sangoma S508 and S514 cards
+	x25_508.sfm	X25 Firmware for Sangoma S508 card.
+
+
 REVISION HISTORY
 
-2.1.1   Nov 09, 1999 		- New code for S514PCI card
-                                - Completely redesigned drivers
-                                  fully tested and optimized.
-
-2.0.8   Nov 02, 1999            - Fixed up the X25API code.
-                                - Clear call bug fixed.i
-                                - Enabled driver for multi-card
-                                  operation.                                
-
-2.0.7   Aug 26, 1999		- Merged X25API code into WANPIPE.
-				- Fixed a memory leak for X25API
-				- Updated the X25API code for 2.2.X kernels.
-				- Improved NEM handling.
-
-2.0.6   Aug 17, 1999            - Kernel patch works for both 2.2.10 and 2.2.11 kernels
-                                - Fixed up 2.0.5 installation bugs
-                                - No functional difference between 2.0.6 and 2.0.5         
-
-2.0.5   Aug 12, 1999            - NEW PPP, interrupt drive code
-				- NEW X25 Xpipmon debugger
-				- Comments added to setup scripts
-				- Numerous bug fixes
-
-2.0.4	Nov 26, 1998		- NEW Cisco Dual Port support. 
-				- NEW support for BiSync Streaming API.
-				- NEW support for HDLC (LAPB) API.
-				- WANPIPE provides an API for application 
-				  development using the BSD socket interface.
-
-2.0.3 	Aug 25, 1998		- NEW support for Cisco HDLC, with cpipemon 
-				  utility for monitoring
-				- CIR support for Frame-relay
-				- Support for PAP and CHAP for ppp has been 
-				  implemented
-				- Dynamic IP assignment for PPP
-				- Multiple channel IPX support for Frame-relay 
-				  and X25
-				- Inverse Arp support for Frame-relay
-				- FT1 Configuration utility for linux
-				- Man Pages for router.conf, router, sdladump,
-				  cfgft1, fpipemon, ppipemon and cpipemon
-
-2.0.2	Dev 09, 1997	      - Implemented PAP and CHAP for ppp.
-
-2.0.1	Nov 28, 1997	      -	Protection of "enable_irq()" while
-                                "disable_irq()" has been enabled from any other
-                                routine (for Frame Relay, PPP and X25).
-			      - Added additional Stats for Fpipemon and Ppipemon
-                              - Improved Load Sharing for multiple boards.
-
-2.0.0   Nov 07, 1997          - Implemented protection of RACE conditions by
-                                critical flags for FRAME RELAY and PPP.
-                              - DLCI List interrupt mode implemented.
-                              - IPX support in FRAME RELAY and PPP.
-                              - IPX Server Support (MARS)
-                              - More driver specific stats included in FPIPEMON
-                                and PIPEMON.
-
-1.0.5   July 28, 1997         - Configurable T391,T392,N391,N392,N393 for Frame
-                                Relay in router.conf.
-                              - Configurable Memory Address through router.conf
-                                for Frame Relay, PPP and X.25. (commenting this
-                                out enables auto-detection).
-                              - Fixed freeing up received buffers using kfree()
-                                for Frame Relay and X.25.
-                              - Protect sdla_peek() by calling save_flags(),
-                                cli() and restore_flags().
-                              - Changed number of Trace elements from 32 to 20
-                              - Added DLCI specific data monitoring in FPIPEMON.
-
-1.0.4   July 10, 1997         - S508/FT1 monitoring capability in fpipemon and
-                                ppipemon utilities.
-                              - Configurable TTL for UDP packets.
-                              - Multicast and Broadcast IP source addresses are
-                                silently discarded.
-
-1.0.3	June 3, 1997
-	 		      -	UDP port for multiple boards (Frame relay, PPP)
-	 			Continuous Transmission of Configure Request 
-			      -	Packet for PPP (this support is only added for 
-			   	508 cards)
-	 		      -	Connection Timeout for PPP changed from 900 to 0
-	 	              -	Flow Control for multiple boards and multiple 
-				channels (Frame Relay)
-
-1.0.1	January 30, 1997
+1.0.0	December 31, 1996	Initial version
+
+1.0.1	January 30, 1997	Status and statistics can be read via /proc
+				filesystem entries.
+
+1.0.2   April 30, 1997          Added UDP management via monitors.
+
+1.0.3	June 3, 1997		UDP management for multiple boards using Frame
+				Relay and PPP
+				Enabled continuous transmission of Configure 
+				Request Packet for PPP (for 508 only)
+				Connection Timeout for PPP changed from 900 to 0
+				Flow Control Problem fixed for Frame Relay
+
+1.0.4	July 10, 1997		S508/FT1 monitoring capability in fpipemon and
+				ppipemon utilities.
+				Configurable TTL for UDP packets.
+				Multicast and Broadcast IP source addresses are
+				silently discarded.
+
+1.0.5	July 28, 1997		Configurable T391,T392,N391,N392,N393 for Frame
+				Relay in router.conf.
+				Configurable Memory Address through router.conf 
+				for Frame Relay, PPP and X.25. (commenting this
+ 				out enables auto-detection).
+				Fixed freeing up received buffers using kfree()
+ 				for Frame Relay and X.25.
+				Protect sdla_peek() by calling save_flags(),
+				cli() and restore_flags().
+				Changed number of Trace elements from 32 to 20
+				Added DLCI specific data monitoring in FPIPEMON. 
+2.0.0	Nov 07, 1997		Implemented protection of RACE conditions by 
+				critical flags for FRAME RELAY and PPP.
+				DLCI List interrupt mode implemented.
+				IPX support in FRAME RELAY and PPP.
+				IPX Server Support (MARS)
+				More driver specific stats included in FPIPEMON
+				and PIPEMON.
+
+2.0.1	Nov 28, 1997		Bug Fixes for version 2.0.0.
+				Protection of "enable_irq()" while 
+				"disable_irq()" has been enabled from any other
+				routine (for Frame Relay, PPP and X25).
+				Added additional Stats for Fpipemon and Ppipemon
+				Improved Load Sharing for multiple boards
+
+2.0.2	Dec 09, 1997		Support for PAP and CHAP for ppp has been
+				implemented.
+
+2.0.3	Aug 15, 1998		New release supporting Cisco HDLC, CIR for Frame
+				relay, Dynamic IP assignment for PPP and Inverse
+				Arp support for Frame-relay.  Man Pages are 
+				included for better support and a new utility
+				for configuring FT1 cards.
+
+2.0.4	Dec 09, 1998	        Dual Port support for Cisco HDLC.
+				Support for HDLC (LAPB) API.
+				Supports BiSync Streaming code for S502E 
+				and S503 cards.
+				Support for Streaming HDLC API.
+				Provides a BSD socket interface for 
+				creating applications using BiSync
+   				streaming.        
+
+2.0.5   Aug 04, 1999 		CHDLC initializatin bug fix.
+				PPP interrupt driven driver: 
+  				Fix to the PPP line hangup problem.
+				New PPP firmware
+				Added comments to the startup SYSTEM ERROR messages
+				Xpipemon debugging application for the X25 protocol
+				New USER_MANUAL.txt
+				Fixed the odd boundary 4byte writes to the board.
+				BiSync Streaming code has been taken out.  
+				 Available as a patch.
+				Streaming HDLC API has been taken out.  
+				 Available as a patch.                 
+
+2.0.6   Aug 17, 1999		Increased debugging in statup scripts
+				Fixed insallation bugs from 2.0.5
+				Kernel patch works for both 2.2.10 and 2.2.11 kernels.
+				There is no functional difference between the two packages         
+
+2.0.7   Aug 26, 1999		o  Merged X25API code into WANPIPE.
+				o  Fixed a memeory leak for X25API
+				o  Updated the X25API code for 2.2.X kernels.
+				o  Improved NEM handling.   
+
+2.1.0	Oct 25, 1999		o New code for S514 PCI Card
+				o New CHDLC and Frame Relay drivers
+				o PPP and X25 are not supported in this release    
+
+2.1.1	Nov 30, 1999		o PPP support for S514 PCI Cards
+
+2.1.3   Apr 06, 2000		o Socket based x25api 
+				o Socket based chdlc api
+				o Socket based fr api
+				o Dual Port Receive only CHDLC support.
+				o Asynchronous CHDLC support (Secondary Port)
+				o cfgft1 GUI csu/dsu configurator
+				o wancfg GUI configuration file 
+				  configurator.
+				o Architectual directory changes.
+
+beta-2.1.4 Jul 2000		o Dynamic interface configuration:
+					Network interfaces reflect the state
+					of protocol layer.  If the protocol becomes
+					disconnected, driver will bring down
+					the interface.  Once the protocol reconnects
+					the interface will be brought up. 
+					
+					Note: This option is turned off by default.
+
+				o Dynamic wanrouter setup using 'wanconfig':
+					wanconfig utility can be used to
+					shutdown,restart,start or reconfigure 
+					a virtual circuit dynamically.
+				     
+					Frame Relay:  Each DLCI can be: 
+						      created,stopped,restarted and reconfigured
+						      dynamically using wanconfig.
+					
+						      ex: wanconfig card wanpipe1 dev wp1_fr16 up
+				  
+				o Wanrouter startup via command line arguments:
+					wanconfig also supports wanrouter startup via command line
+					arguments.  Thus, there is no need to create a wanpipe#.conf
+					configuration file.  
+
+				o Socket based x25api update/bug fixes.
+					Added support for LCN numbers greater than 255.
+					Option to pass up modem messages.
+					Provided a PCI IRQ check, so a single S514
+					card is guaranteed to have a non-sharing interrupt.
+
+				o Fixes to the wancfg utility.
+				o New FT1 debugging support via *pipemon utilities.
+				o Frame Relay ARP support Enabled.
+
+beta3-2.1.4 Jul 2000		o X25 M_BIT Problem fix.
+				o Added the Multi-Port PPP
+				  Updated utilites for the Multi-Port PPP.
+
+2.1.4	Aut 2000
+				o In X25API:
+					Maximum packet an application can send
+					to the driver has been extended to 4096 bytes.
+
+					Fixed the x25 startup bug. Enable 
+					communications only after all interfaces
+					come up.  HIGH SVC/PVC is used to calculate
+					the number of channels.
+					Enable protocol only after all interfaces
+					are enabled.
+
+				o Added an extra state to the FT1 config, kernel module.
+				o Updated the pipemon debuggers.
+
+				o Blocked the Multi-Port PPP from running on kernels
+				  2.2.16 or greater, due to syncppp kernel module
+				  change. 
+	  
+beta1-2.1.5 	Nov 15 2000
+				o Fixed the MulitPort PPP Support for kernels 2.2.16 and above.
+				  2.2.X kernels only
+
+				o Secured the driver UDP debugging calls
+					- All illegal netowrk debugging calls are reported to
+					  the log.
+					- Defined a set of allowed commands, all other denied.
+					
+				o Cpipemon
+					- Added set FT1 commands to the cpipemon. Thus CSU/DSU
+					  configuraiton can be performed using cpipemon.
+					  All systems that cannot run cfgft1 GUI utility should
+					  use cpipemon to configure the on board CSU/DSU.
+
+
+				o Keyboard Led Monitor/Debugger
+					- A new utilty /usr/sbin/wpkbdmon uses keyboard leds
+					  to convey operatinal statistic information of the 
+					  Sangoma WANPIPE cards.
+					NUM_LOCK    = Line State  (On=connected,    Off=disconnected)
+					CAPS_LOCK   = Tx data     (On=transmitting, Off=no tx data)
+					SCROLL_LOCK = Rx data     (On=receiving,    Off=no rx data
+					
+				o Hardware probe on module load and dynamic device allocation
+					- During WANPIPE module load, all Sangoma cards are probed
+					  and found information is printed in the /var/log/messages.
+					- If no cards are found, the module load fails.
+					- Appropriate number of devices are dynamically loaded 
+					  based on the number of Sangoma cards found.
+
+					  Note: The kernel configuraiton option 
+						CONFIG_WANPIPE_CARDS has been taken out.
+					
+				o Fixed the Frame Relay and Chdlc network interfaces so they are
+				  compatible with libpcap libraries.  Meaning, tcpdump, snort,
+				  ethereal, and all other packet sniffers and debuggers work on
+				  all WANPIPE netowrk interfaces.
+					- Set the network interface encoding type to ARPHRD_PPP.
+					  This tell the sniffers that data obtained from the
+					  network interface is in pure IP format.
+				  Fix for 2.2.X kernels only.
+				
+				o True interface encoding option for Frame Relay and CHDLC
+					- The above fix sets the network interface encoding
+					  type to ARPHRD_PPP, however some customers use
+					  the encoding interface type to determine the
+					  protocol running.  Therefore, the TURE ENCODING
+					  option will set the interface type back to the
+					  original value.  
+
+					  NOTE: If this option is used with Frame Relay and CHDLC
+						libpcap library support will be broken.  
+						i.e. tcpdump will not work.
+					Fix for 2.2.x Kernels only.
+						
+				o Ethernet Bridgind over Frame Relay
+					- The Frame Relay bridging has been developed by 
+					  Kristian Hoffmann and Mark Wells.  
+					- The Linux kernel bridge is used to send ethernet 
+					  data over the frame relay links.
+					For 2.2.X Kernels only.
+
+				o Added extensive 2.0.X support. Most new features of
+				  2.1.5 for protocols Frame Relay, PPP and CHDLC are
+				  supported under 2.0.X kernels. 
+
+beta1-2.2.0 	Dec 30 2000
+				o Updated drivers for 2.4.X kernels.
+				o Updated drivers for SMP support.
+				o X25API is now able to share PCI interrupts.
+				o Took out a general polling routine that was used
+				  only by X25API. 
+				o Added appropriate locks to the dynamic reconfiguration
+				  code.
+				o Fixed a bug in the keyboard debug monitor.
+
+beta2-2.2.0	Jan 8 2001
+				o Patches for 2.4.0 kernel
+				o Patches for 2.2.18 kernel
+				o Minor updates to PPP and CHLDC drivers.
+				  Note: No functinal difference. 
+
+beta3-2.2.9	Jan 10 2001
+				o I missed the 2.2.18 kernel patches in beta2-2.2.0
+				  release.  They are included in this release.
+
+Stable Release
+2.2.0		Feb 01 2001
+				o Bug fix in wancfg GUI configurator.
+					The edit function didn't work properly.
+
+
+bata1-2.2.1	Feb 09 2001
+			o WANPIPE TTY Driver emulation. 
+			  Two modes of operation Sync and Async.
+				Sync: Using the PPPD daemon, kernel SyncPPP layer
+				      and the Wanpipe sync TTY driver: a PPP protocol 
+				      connection can be established via Sangoma adapter, over
+				      a T1 leased line.
+			
+				      The 2.4.0 kernel PPP layer supports MULTILINK
+				      protocol, that can be used to bundle any number of Sangoma
+				      adapters (T1 lines) into one, under a single IP address.
+				      Thus, efficiently obtaining multiple T1 throughput. 
+
+				      NOTE: The remote side must also implement MULTILINK PPP
+					    protocol.
+
+				Async:Using the PPPD daemon, kernel AsyncPPP layer
+				      and the WANPIPE async TTY driver: a PPP protocol
+				      connection can be established via Sangoma adapter and
+				      a modem, over a telephone line.
+
+				      Thus, the WANPIPE async TTY driver simulates a serial
+				      TTY driver that would normally be used to interface the 
+				      MODEM to the linux kernel.
+				
+			o WANPIPE PPP Backup Utility
+				This utility will monitor the state of the PPP T1 line.
+				In case of failure, a dial up connection will be established
+				via pppd daemon, ether via a serial tty driver (serial port), 
+				or a WANPIPE async TTY driver (in case serial port is unavailable).
+				
+				Furthermore, while in dial up mode, the primary PPP T1 link
+				will be monitored for signs of life.  
+
+				If the PPP T1 link comes back to life, the dial up connection
+				will be shutdown and T1 line re-established.
+			
+
+			o New Setup installation script.
+				Option to UPGRADE device drivers if the kernel source has
+				already been patched with WANPIPE.
+
+				Option to COMPILE WANPIPE modules against the currently 
+				running kernel, thus no need for manual kernel and module
+				re-compilatin.
+			
+			o Updates and Bug Fixes to wancfg utility.
+
+bata2-2.2.1	Feb 20 2001
+
+			o Bug fixes to the CHDLC device drivers.
+				The driver had compilation problmes under kernels
+				2.2.14 or lower.
+
+			o Bug fixes to the Setup installation script.
+				The device drivers compilation options didn't work
+				properly.
+
+			o Update to the wpbackupd daemon.  
+				Optimized the cross-over times, between the primary
+				link and the backup dialup.
+
+beta3-2.2.1	Mar 02 2001
+			o Patches for 2.4.2 kernel.
+
+			o Bug fixes to util/ make files.
+			o Bug fixes to the Setup installation script.
+
+			o Took out the backupd support and made it into
+			  as separate package.
+			  
+beta4-2.2.1     Mar 12 2001
+
+		o Fix to the Frame Relay Device driver.
+			IPSAC sends a packet of zero length
+			header to the frame relay driver.  The
+			driver tries to push its own 2 byte header
+			into the packet, which causes the driver to
+			crash.
+
+		o Fix the WANPIPE re-configuration code.
+			Bug was found by trying to run  the cfgft1 while the
+			interface was already running.  
+
+		o Updates to cfgft1.
+			Writes a wanpipe#.cfgft1 configuration file
+			once the CSU/DSU is configured. This file can
+			holds the current CSU/DSU configuration.
+
 
-			      -	Implemented user-readable status and statistics
-				via /proc filesystem
 
-1.0.0	December 31, 1996
+>>>>>> END OF README <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
-			      -	Initial version
 
->>>>>> END <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
diff -u --recursive --new-file v2.4.3/linux/Documentation/networking/wanpipe.txt linux/Documentation/networking/wanpipe.txt
--- v2.4.3/linux/Documentation/networking/wanpipe.txt	Fri Jul 28 12:50:52 2000
+++ linux/Documentation/networking/wanpipe.txt	Thu Apr 12 12:11:39 2001
@@ -1,32 +1,100 @@
 ------------------------------------------------------------------------------
 Linux WAN Router Utilities Package
 ------------------------------------------------------------------------------
-Version 2.1.1
-Nov 08, 1999
+Version 2.2.1 
+Mar 28, 2001
 Author: Nenad Corbic <ncorbic@sangoma.com>
-Copyright (c) 1995-1999 Sangoma Technologies Inc.
+Copyright (c) 1995-2001 Sangoma Technologies Inc.
 ------------------------------------------------------------------------------
 
 INTRODUCTION
 
-This is a set of utilities and shell scripts you need in order to be able to
-use Linux kernel-level WAN Router.  Please read WAN Router User's manual
-(router.txt) and WANPIPE driver documentation found in /usr/lib/router/doc
-directory for installation and configuration instructions.
+Wide Area Networks (WANs) are used to interconnect Local Area Networks (LANs)
+and/or stand-alone hosts over vast distances with data transfer rates
+significantly higher than those achievable with commonly used dial-up
+connections.
+
+Usually an external device called `WAN router' sitting on your local network
+or connected to your machine's serial port provides physical connection to
+WAN.  Although router's job may be as simple as taking your local network
+traffic, converting it to WAN format and piping it through the WAN link, these
+devices are notoriously expensive, with prices as much as 2 - 5 times higher
+then the price of a typical PC box.
+
+Alternatively, considering robustness and multitasking capabilities of Linux,
+an internal router can be built (most routers use some sort of stripped down
+Unix-like operating system anyway). With a number of relatively inexpensive WAN
+interface cards available on the market, a perfectly usable router can be
+built for less than half a price of an external router.  Yet a Linux box
+acting as a router can still be used for other purposes, such as fire-walling,
+running FTP, WWW or DNS server, etc.
+
+This kernel module introduces the notion of a WAN Link Driver (WLD) to Linux
+operating system and provides generic hardware-independent services for such
+drivers.  Why can existing Linux network device interface not be used for
+this purpose?  Well, it can.  However, there are a few key differences between
+a typical network interface (e.g. Ethernet) and a WAN link.
+
+Many WAN protocols, such as X.25 and frame relay, allow for multiple logical
+connections (known as `virtual circuits' in X.25 terminology) over a single
+physical link.  Each such virtual circuit may (and almost always does) lead
+to a different geographical location and, therefore, different network.  As a
+result, it is the virtual circuit, not the physical link, that represents a
+route and, therefore, a network interface in Linux terms.
+
+To further complicate things, virtual circuits are usually volatile in nature
+(excluding so called `permanent' virtual circuits or PVCs).  With almost no
+time required to set up and tear down a virtual circuit, it is highly desirable
+to implement on-demand connections in order to minimize network charges.  So
+unlike a typical network driver, the WAN driver must be able to handle multiple
+network interfaces and cope as multiple virtual circuits come into existence
+and go away dynamically.
+ 
+Last, but not least, WAN configuration is much more complex than that of say
+Ethernet and may well amount to several dozens of parameters.  Some of them
+are "link-wide"  while others are virtual circuit-specific.  The same holds
+true for WAN statistics which is by far more extensive and extremely useful
+when troubleshooting WAN connections.  Extending the ifconfig utility to suit
+these needs may be possible, but does not seem quite reasonable.  Therefore, a
+WAN configuration utility and corresponding application programmer's interface
+is needed for this purpose.
+
+Most of these problems are taken care of by this module.  Its goal is to
+provide a user with more-or-less standard look and feel for all WAN devices and
+assist a WAN device driver writer by providing common services, such as:
+
+ o User-level interface via /proc file system
+ o Centralized configuration
+ o Device management (setup, shutdown, etc.)
+ o Network interface management (dynamic creation/destruction)
+ o Protocol encapsulation/decapsulation
 
-You can find the latest version of this software in /pub/linux directory on
-Sangoma Technologies' anonymous FTP server (ftp.sangoma.com). 
+To ba able to use the Linux WAN Router you will also need a WAN Tools package
+available from
+
+	ftp.sangoma.com/pub/linux/current_wanpipe/wanpipe-X.Y.Z.tgz
+
+where vX.Y.Z represent the wanpipe version number.
 
 For technical questions and/or comments please e-mail to ncorbic@sangoma.com.
 For general inquiries please contact Sangoma Technologies Inc. by
 
 	Hotline:	1-800-388-2475	(USA and Canada, toll free)
-	Phone:		(905) 474-1990
+	Phone:		(905) 474-1990  ext: 106
 	Fax:		(905) 474-9223
 	E-mail:		dm@sangoma.com	(David Mandelstam)
 	WWW:		http://www.sangoma.com
 
 
+INSTALLATION
+
+Please read the WanpipeForLinux.pdf manual on how to 
+install the WANPIPE tools and drivers properly. 
+
+
+After installing wanpipe package: /usr/local/wanrouter/doc. 
+On the ftp.sangoma.com : /linux/current_wanpipe/doc
+
 
 COPYRIGHT AND LICENSING INFORMATION
 
@@ -47,7 +115,7 @@
 ACKNOWLEDGEMENTS
 
 This product is based on the WANPIPE(tm) Multiprotocol WAN Router developed
-by Sangoma Technologies Inc. for Linux 2.2.x.  Success of the WANPIPE
+by Sangoma Technologies Inc. for Linux 2.0.x and 2.2.x.  Success of the WANPIPE
 together with the next major release of Linux kernel in summer 1996 commanded
 adequate changes to the WANPIPE code to take full advantage of new Linux
 features.
@@ -75,22 +143,33 @@
 
 NEW IN THIS RELEASE
 
-o Renamed startup script to wanrouter
-o Option to turn off/on each router 
-  separately
-o New source directory /usr/lib/wanrouter
-o New PPP driver 
-o X25 is not supported in this release 
+	o Updated the WANCFG utility
+		Calls the pppconfig to configure the PPPD
+		for async connections.
+
+	o Added the PPPCONFIG utility
+		Used to configure the PPPD dameon for the
+		WANPIPE Async PPP and standard serial port.
+		The wancfg calls the pppconfig to configure
+		the pppd.
+
+	o Fixed the PCI autodetect feature.  
+		The SLOT 0 was used as an autodetect option
+		however, some high end PC's slot numbers start
+		from 0. 
 
+	o This release has been tested with the new backupd
+	  daemon release.
 	
+
 PRODUCT COMPONENTS AND RELATED FILES
 
-/etc:
+/etc: (or user defined)
 	wanpipe1.conf	default router configuration file
-	wanrouter.rc	meta-configuration file (used by the Setup script)
 
 /lib/modules/X.Y.Z/misc:
 	wanrouter.o	router kernel loadable module
+	af_wanpipe.o	wanpipe api socket module
 
 /lib/modules/X.Y.Z/net:
 	sdladrv.o	Sangoma SDLA support module
@@ -102,64 +181,93 @@
 	{name}		reads WAN driver statistics
 
 /usr/sbin:
-	wanrouter	router start-up script
-	wanconfig	router configuration utility
+	wanrouter	wanrouter start-up script
+	wanconfig	wanrouter configuration utility
 	sdladump	WANPIPE adapter memory dump utility
         fpipemon        Monitor for Frame Relay
         cpipemon        Monitor for Cisco HDLC
+	ppipemon 	Monitor for PPP
+	xpipemon 	Monitor for X25
+	wpkbdmon        WANPIPE keyboard led monitor/debugger
 
-/usr/lib/wanrouter:
+/usr/local/wanrouter:
 	README		this file
 	COPYING		GNU General Public License
 	Setup		installation script
-	Configure	configuration script
 	Filelist	distribution definition file
+	wanrouter.rc	meta-configuration file 
+			(used by the Setup and wanrouter script)
 
-/usr/lib/wanrouter/doc:
-	WANPIPE_USER_MANUAL.txt WAN Router User's Manual
-	WANPIPE_CONFIG.txt	WAN Configuration Manual
-
-/usr/lib/wanrouter/interfaces:
-	*		interface configuration files (TCP/IP configuration)
-
-/usr/lib/wanrouter/patches:
-	wanrouter-22.gz	patch for Linux kernel 2.2.10 and 2.2.11 
-			(compatible for all 2.2.X kernels)
-	wanrouter-20.gz patch for Linux kernel 2.0.36 
+/usr/local/wanrouter/doc:
+	wanpipeForLinux.pdf 	WAN Router User's Manual
 
-	Fix_2.2.11.gz   patch to fix the 2.2.11 kernel so other patches
-                        can be applied properly.
+/usr/local/wanrouter/patches:
+	wanrouter-v2213.gz  	patch for Linux kernels 2.2.11 up to 2.2.13.
+	wanrouter-v2214.gz	patch for Linux kernel 2.2.14. 
+	wanrouter-v2215.gz	patch for Linux kernels 2.2.15 to 2.2.17.
+	wanrouter-v2218.gz	patch for Linux kernels 2.2.18 and up.
+	wanrouter-v240.gz	patch for Linux kernel 2.4.0.  
+	wanrouter-v242.gz	patch for Linux kernel 2.4.2 and up.
+	wanrouter-v2034.gz	patch for Linux kernel 2.0.34
+	wanrouter-v2036.gz 	patch for Linux kernel 2.0.36 and up. 
+
+/usr/local/wanrouter/patches/kdrivers:
+	Sources of the latest WANPIPE device drivers.
+	These are used to UPGRADE the linux kernel to the newest
+	version if the kernel source has already been pathced with
+	WANPIPE drivers.
 
-/usr/lib/wanrouter/samples:
+/usr/local/wanrouter/samples:
 	interface	sample interface configuration file
 	wanpipe1.cpri 	CHDLC primary port
      	wanpipe2.csec 	CHDLC secondary port
      	wanpipe1.fr   	Frame Relay protocol
      	wanpipe1.ppp  	PPP protocol ) 
+	wanpipe1.asy	CHDLC ASYNC protocol
+	wanpipe1.x25	X25 protocol
+	wanpipe1.stty	Sync TTY driver (Used by Kernel PPPD daemon)
+	wanpipe1.atty	Async TTY driver (Used by Kernel PPPD daemon)
 	wanrouter.rc	sample meta-configuration file
 
-/usr/lib/wanrouter/src:
-	*		wan-tools source code
+/usr/local/wanrouter/util:
+	*		wan-tools utilities source code
+
+/usr/local/wanrouter/api/x25:
+	*		x25 api sample programs.
+/usr/local/wanrouter/api/chdlc:
+	*		chdlc api sample programs.
+/usr/local/wanrouter/api/fr:
+	*		fr api sample programs.
+/usr/local/wanrouter/config/wancfg:
+	wancfg		WANPIPE GUI configuration program.
+                        Creates wanpipe#.conf files. 
+/usr/local/wanrouter/config/cfgft1:
+	cfgft1		GUI CSU/DSU configuration program.
 
 /usr/include/linux:
 	wanrouter.h	router API definitions
 	wanpipe.h	WANPIPE API definitions
 	sdladrv.h	SDLA support module API definitions
 	sdlasfm.h	SDLA firmware module definitions
+	if_wanpipe.h	WANPIPE Socket definitions
+	if_wanpipe_common.h	WANPIPE Socket/Driver common definitions.
+	sdlapci.h	WANPIPE PCI definitions
+	
 
-/usr/src/linux/net/router:
-	*		router source code
+/usr/src/linux/net/wanrouter:
+	*		wanrouter source code
 
 /var/log:
-	wanrouter	router start-up log (created by the Setup script)
+	wanrouter	wanrouter start-up log (created by the Setup script)
 
-/var/lock:
-	wanrouter	router lock file (created by the Setup script)
+/var/lock:  (or /var/lock/subsys for RedHat)
+	wanrouter	wanrouter lock file (created by the Setup script)
 
-/usr/lib/wanrouter/wanpipe:
+/usr/local/wanrouter/firmware:
 	fr514.sfm	Frame relay firmware for Sangoma S508/S514 card
 	cdual514.sfm	Dual Port Cisco HDLC firmware for Sangoma S508/S514 card
 	ppp514.sfm      PPP Firmware for Sangoma S508 and S514 cards
+	x25_508.sfm	X25 Firmware for Sangoma S508 card.
 
 
 REVISION HISTORY
@@ -228,7 +336,7 @@
 				creating applications using BiSync
    				streaming.        
 
-2.0.5   Aug 04, 1999 		CHDLC initialization bug fix.
+2.0.5   Aug 04, 1999 		CHDLC initializatin bug fix.
 				PPP interrupt driven driver: 
   				Fix to the PPP line hangup problem.
 				New PPP firmware
@@ -241,17 +349,274 @@
 				Streaming HDLC API has been taken out.  
 				 Available as a patch.                 
 
-2.0.6   Aug 17, 1999		Increased debugging in startup scripts
-				Fixed installation bugs from 2.0.5
+2.0.6   Aug 17, 1999		Increased debugging in statup scripts
+				Fixed insallation bugs from 2.0.5
 				Kernel patch works for both 2.2.10 and 2.2.11 kernels.
 				There is no functional difference between the two packages         
 
 2.0.7   Aug 26, 1999		o  Merged X25API code into WANPIPE.
-				o  Fixed a memory leak for X25API
+				o  Fixed a memeory leak for X25API
 				o  Updated the X25API code for 2.2.X kernels.
 				o  Improved NEM handling.   
 
 2.1.0	Oct 25, 1999		o New code for S514 PCI Card
 				o New CHDLC and Frame Relay drivers
 				o PPP and X25 are not supported in this release    
+
+2.1.1	Nov 30, 1999		o PPP support for S514 PCI Cards
+
+2.1.3   Apr 06, 2000		o Socket based x25api 
+				o Socket based chdlc api
+				o Socket based fr api
+				o Dual Port Receive only CHDLC support.
+				o Asynchronous CHDLC support (Secondary Port)
+				o cfgft1 GUI csu/dsu configurator
+				o wancfg GUI configuration file 
+				  configurator.
+				o Architectual directory changes.
+
+beta-2.1.4 Jul 2000		o Dynamic interface configuration:
+					Network interfaces reflect the state
+					of protocol layer.  If the protocol becomes
+					disconnected, driver will bring down
+					the interface.  Once the protocol reconnects
+					the interface will be brought up. 
+					
+					Note: This option is turned off by default.
+
+				o Dynamic wanrouter setup using 'wanconfig':
+					wanconfig utility can be used to
+					shutdown,restart,start or reconfigure 
+					a virtual circuit dynamically.
+				     
+					Frame Relay:  Each DLCI can be: 
+						      created,stopped,restarted and reconfigured
+						      dynamically using wanconfig.
+					
+						      ex: wanconfig card wanpipe1 dev wp1_fr16 up
+				  
+				o Wanrouter startup via command line arguments:
+					wanconfig also supports wanrouter startup via command line
+					arguments.  Thus, there is no need to create a wanpipe#.conf
+					configuration file.  
+
+				o Socket based x25api update/bug fixes.
+					Added support for LCN numbers greater than 255.
+					Option to pass up modem messages.
+					Provided a PCI IRQ check, so a single S514
+					card is guaranteed to have a non-sharing interrupt.
+
+				o Fixes to the wancfg utility.
+				o New FT1 debugging support via *pipemon utilities.
+				o Frame Relay ARP support Enabled.
+
+beta3-2.1.4 Jul 2000		o X25 M_BIT Problem fix.
+				o Added the Multi-Port PPP
+				  Updated utilites for the Multi-Port PPP.
+
+2.1.4	Aut 2000
+				o In X25API:
+					Maximum packet an application can send
+					to the driver has been extended to 4096 bytes.
+
+					Fixed the x25 startup bug. Enable 
+					communications only after all interfaces
+					come up.  HIGH SVC/PVC is used to calculate
+					the number of channels.
+					Enable protocol only after all interfaces
+					are enabled.
+
+				o Added an extra state to the FT1 config, kernel module.
+				o Updated the pipemon debuggers.
+
+				o Blocked the Multi-Port PPP from running on kernels
+				  2.2.16 or greater, due to syncppp kernel module
+				  change. 
+	  
+beta1-2.1.5 	Nov 15 2000
+				o Fixed the MulitPort PPP Support for kernels 2.2.16 and above.
+				  2.2.X kernels only
+
+				o Secured the driver UDP debugging calls
+					- All illegal netowrk debugging calls are reported to
+					  the log.
+					- Defined a set of allowed commands, all other denied.
+					
+				o Cpipemon
+					- Added set FT1 commands to the cpipemon. Thus CSU/DSU
+					  configuraiton can be performed using cpipemon.
+					  All systems that cannot run cfgft1 GUI utility should
+					  use cpipemon to configure the on board CSU/DSU.
+
+
+				o Keyboard Led Monitor/Debugger
+					- A new utilty /usr/sbin/wpkbdmon uses keyboard leds
+					  to convey operatinal statistic information of the 
+					  Sangoma WANPIPE cards.
+					NUM_LOCK    = Line State  (On=connected,    Off=disconnected)
+					CAPS_LOCK   = Tx data     (On=transmitting, Off=no tx data)
+					SCROLL_LOCK = Rx data     (On=receiving,    Off=no rx data
+					
+				o Hardware probe on module load and dynamic device allocation
+					- During WANPIPE module load, all Sangoma cards are probed
+					  and found information is printed in the /var/log/messages.
+					- If no cards are found, the module load fails.
+					- Appropriate number of devices are dynamically loaded 
+					  based on the number of Sangoma cards found.
+
+					  Note: The kernel configuraiton option 
+						CONFIG_WANPIPE_CARDS has been taken out.
+					
+				o Fixed the Frame Relay and Chdlc network interfaces so they are
+				  compatible with libpcap libraries.  Meaning, tcpdump, snort,
+				  ethereal, and all other packet sniffers and debuggers work on
+				  all WANPIPE netowrk interfaces.
+					- Set the network interface encoding type to ARPHRD_PPP.
+					  This tell the sniffers that data obtained from the
+					  network interface is in pure IP format.
+				  Fix for 2.2.X kernels only.
+				
+				o True interface encoding option for Frame Relay and CHDLC
+					- The above fix sets the network interface encoding
+					  type to ARPHRD_PPP, however some customers use
+					  the encoding interface type to determine the
+					  protocol running.  Therefore, the TURE ENCODING
+					  option will set the interface type back to the
+					  original value.  
+
+					  NOTE: If this option is used with Frame Relay and CHDLC
+						libpcap library support will be broken.  
+						i.e. tcpdump will not work.
+					Fix for 2.2.x Kernels only.
+						
+				o Ethernet Bridgind over Frame Relay
+					- The Frame Relay bridging has been developed by 
+					  Kristian Hoffmann and Mark Wells.  
+					- The Linux kernel bridge is used to send ethernet 
+					  data over the frame relay links.
+					For 2.2.X Kernels only.
+
+				o Added extensive 2.0.X support. Most new features of
+				  2.1.5 for protocols Frame Relay, PPP and CHDLC are
+				  supported under 2.0.X kernels. 
+
+beta1-2.2.0 	Dec 30 2000
+				o Updated drivers for 2.4.X kernels.
+				o Updated drivers for SMP support.
+				o X25API is now able to share PCI interrupts.
+				o Took out a general polling routine that was used
+				  only by X25API. 
+				o Added appropriate locks to the dynamic reconfiguration
+				  code.
+				o Fixed a bug in the keyboard debug monitor.
+
+beta2-2.2.0	Jan 8 2001
+				o Patches for 2.4.0 kernel
+				o Patches for 2.2.18 kernel
+				o Minor updates to PPP and CHLDC drivers.
+				  Note: No functinal difference. 
+
+beta3-2.2.9	Jan 10 2001
+				o I missed the 2.2.18 kernel patches in beta2-2.2.0
+				  release.  They are included in this release.
+
+Stable Release
+2.2.0		Feb 01 2001
+				o Bug fix in wancfg GUI configurator.
+					The edit function didn't work properly.
+
+
+bata1-2.2.1	Feb 09 2001
+			o WANPIPE TTY Driver emulation. 
+			  Two modes of operation Sync and Async.
+				Sync: Using the PPPD daemon, kernel SyncPPP layer
+				      and the Wanpipe sync TTY driver: a PPP protocol 
+				      connection can be established via Sangoma adapter, over
+				      a T1 leased line.
+			
+				      The 2.4.0 kernel PPP layer supports MULTILINK
+				      protocol, that can be used to bundle any number of Sangoma
+				      adapters (T1 lines) into one, under a single IP address.
+				      Thus, efficiently obtaining multiple T1 throughput. 
+
+				      NOTE: The remote side must also implement MULTILINK PPP
+					    protocol.
+
+				Async:Using the PPPD daemon, kernel AsyncPPP layer
+				      and the WANPIPE async TTY driver: a PPP protocol
+				      connection can be established via Sangoma adapter and
+				      a modem, over a telephone line.
+
+				      Thus, the WANPIPE async TTY driver simulates a serial
+				      TTY driver that would normally be used to interface the 
+				      MODEM to the linux kernel.
+				
+			o WANPIPE PPP Backup Utility
+				This utility will monitor the state of the PPP T1 line.
+				In case of failure, a dial up connection will be established
+				via pppd daemon, ether via a serial tty driver (serial port), 
+				or a WANPIPE async TTY driver (in case serial port is unavailable).
+				
+				Furthermore, while in dial up mode, the primary PPP T1 link
+				will be monitored for signs of life.  
+
+				If the PPP T1 link comes back to life, the dial up connection
+				will be shutdown and T1 line re-established.
+			
+
+			o New Setup installation script.
+				Option to UPGRADE device drivers if the kernel source has
+				already been patched with WANPIPE.
+
+				Option to COMPILE WANPIPE modules against the currently 
+				running kernel, thus no need for manual kernel and module
+				re-compilatin.
+			
+			o Updates and Bug Fixes to wancfg utility.
+
+bata2-2.2.1	Feb 20 2001
+
+			o Bug fixes to the CHDLC device drivers.
+				The driver had compilation problmes under kernels
+				2.2.14 or lower.
+
+			o Bug fixes to the Setup installation script.
+				The device drivers compilation options didn't work
+				properly.
+
+			o Update to the wpbackupd daemon.  
+				Optimized the cross-over times, between the primary
+				link and the backup dialup.
+
+beta3-2.2.1	Mar 02 2001
+			o Patches for 2.4.2 kernel.
+
+			o Bug fixes to util/ make files.
+			o Bug fixes to the Setup installation script.
+
+			o Took out the backupd support and made it into
+			  as separate package.
+			  
+beta4-2.2.1     Mar 12 2001
+
+		o Fix to the Frame Relay Device driver.
+			IPSAC sends a packet of zero length
+			header to the frame relay driver.  The
+			driver tries to push its own 2 byte header
+			into the packet, which causes the driver to
+			crash.
+
+		o Fix the WANPIPE re-configuration code.
+			Bug was found by trying to run  the cfgft1 while the
+			interface was already running.  
+
+		o Updates to cfgft1.
+			Writes a wanpipe#.cfgft1 configuration file
+			once the CSU/DSU is configured. This file can
+			holds the current CSU/DSU configuration.
+
+
+
 >>>>>> END OF README <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+
diff -u --recursive --new-file v2.4.3/linux/Documentation/parport.txt linux/Documentation/parport.txt
--- v2.4.3/linux/Documentation/parport.txt	Mon Mar 26 15:41:19 2001
+++ linux/Documentation/parport.txt	Fri Apr  6 10:42:51 2001
@@ -174,7 +174,7 @@
 		peripherals.  This is a port-wide setting, i.e. it
 		applies to all devices on a particular port.
 
-timeslice	The number of miliseconds that a device driver is
+timeslice	The number of milliseconds that a device driver is
 		allowed to keep a port claimed for.  This is advisory,
 		and driver can ignore it if it must.
 
diff -u --recursive --new-file v2.4.3/linux/Documentation/pm.txt linux/Documentation/pm.txt
--- v2.4.3/linux/Documentation/pm.txt	Thu Oct 26 14:22:24 2000
+++ linux/Documentation/pm.txt	Fri Apr  6 10:42:55 2001
@@ -33,7 +33,7 @@
 Go ahead and start both.  If ACPI or APM is not available on your
 system the associated daemon will exit gracefully.
 
-  apmd:   http://linuxcare.com.au/apm/
+  apmd:   http://worldvisions.ca/~apenwarr/apmd/
   acpid:  http://phobos.fs.tum.de/acpi/
 
 Driver Interface
diff -u --recursive --new-file v2.4.3/linux/Documentation/s390/3270.ChangeLog linux/Documentation/s390/3270.ChangeLog
--- v2.4.3/linux/Documentation/s390/3270.ChangeLog	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/s390/3270.ChangeLog	Thu Apr 12 12:03:50 2001
@@ -0,0 +1,15 @@
+ChangeLog for the UTS Global 3270-support patch
+
+Feb 6, 2001:
+	* This changelog is new
+	* tub3270 now supports 3270 console:
+		Specify y for CONFIG_3270 and y for CONFIG_3270_CONSOLE.
+		Support for 3215 will not appear if 3270 console support
+		is chosen.
+		NOTE:  The default is 3270 console support, NOT 3215.
+	* the components are remodularized: added source modules are
+	  tubttybld.c and tubttyscl.c, for screen-building code and
+	  scroll-timeout code.
+	* tub3270 source for this (2.4.0) version is #ifdeffed to
+	  build with both 2.4.0 and 2.2.16.2.
+	* color support and minimal other ESC-sequence support is added.
diff -u --recursive --new-file v2.4.3/linux/Documentation/s390/3270.txt linux/Documentation/s390/3270.txt
--- v2.4.3/linux/Documentation/s390/3270.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/s390/3270.txt	Thu Apr 12 12:03:50 2001
@@ -0,0 +1,280 @@
+IBM 3270 Display System support
+
+This file describes the driver that supports local channel attachment
+of IBM 3270 devices.  It consists of three sections:
+	* Introduction
+	* Installation
+	* Operation
+
+
+INTRODUCTION.
+
+This paper describes installing and operating 3270 devices under
+Linux/390.  A 3270 device is a block-mode rows-and-columns terminal of
+which I'm sure hundreds of millions were sold by IBM and clonemakers
+twenty and thirty years ago.
+
+You may have 3270s in-house and not know it.  If you're using the
+VM-ESA operating system, define a 3270 to your virtual machine by using
+the command "DEF GRAF <hex-address>"  This paper presumes you will be
+defining four 3270s with the CP/CMS commands
+
+	DEF GRAF 620
+	DEF GRAF 621
+	DEF GRAF 622
+	DEF GRAF 623
+
+Your network connection from VM-ESA allows you to use x3270, tn3270, or
+another 3270 emulator, started from an xterm window on your PC or
+workstation.  With the DEF GRAF command, an application such as xterm,
+and this Linux-390 3270 driver, you have another way of talking to your
+Linux box.
+
+This paper covers installation of the driver and operation of a
+dialed-in x3270.
+
+
+HELP !!!
+
+The device name of e.g. /dev/3270/tty620 noted below is at variance
+with "standard" Linux device names.  What should it be?  The portion
+"/dev/3270" was recommended by H. Peter Anvin, maintainer of the
+official Linux major-numbers list; the portion "tty620" was recommended
+by me.  Please send your thoughts on this issue at least to me at
+rbh00@utsglobal.com.  Even if you think it's okay as is, please let me
+know.  Thanks.
+
+
+INSTALLATION.
+
+You install the driver by installing a patch, doing a kernel build, and
+running the configuration script (config3270.sh, in this directory).
+
+WARNING:  If you are using 3270 console support, you must rerun the
+configuration script every time you change the console's address (perhaps
+by using the condev= parameter in silo's /boot/parmfile).  More precisely,
+you should rerun the configuration script every time your set of 3270s,
+including the console 3270, changes subchannel identifier relative to
+one another.  ReIPL as soon as possible after running the configuration
+script and the resulting /tmp/mkdev3270.
+
+If you have chosen to make tub3270 a module, you add a line to
+/etc/modules.conf.  If you are working on a VM virtual machine, you
+can use DEF GRAF to define virtual 3270 devices.  If you generate 3270
+console support, the driver automatically converts your console at boot
+time to a 3270 if it is a 3215.
+
+In brief, these are the steps:
+	1. Install the tub3270 patch
+	2. (If a module) add a line to /etc/modules.conf
+	3. (If VM) define devices with DEF GRAF
+	4. Reboot
+	5. Configure
+
+To test that everything works, assuming VM and x3270,
+	1. Bring up an x3270 window.
+	2. Use the DIAL command in that window.
+	3. You should immediately see a Linux login screen.
+
+Here are the installation steps in detail:
+
+	0.  Retrieve the patch file via anonymous ftp from
+	ftp://ftp.utsglobal.com/pub/tub3270.  The patch is designed
+	to apply smoothly to an IBM 2.4.0 system with no other
+	UTS-Global patches applied.  We know of some easily resolvable
+	conflicts between this and other of our patches.
+
+	1. Apply the patch.  Then do
+		make oldconfig
+			(Reply "y" or "m" for CONFIG_3270; if "y",
+			reply "y" or "n" for CONFIG_3270_CONSOLE)
+		make dep
+		make image
+		make modules
+		make modules_install
+		<run silo in the usual way>
+
+	2. (Perform this step only if you have configured tub3270 as a
+	module.)  Add a line to /etc/modules.conf to automatically
+	load the driver when it's needed.  With this line added,
+	you will see login prompts appear on your 3270s as soon as
+	boot is complete (or with emulated 3270s, as soon as you dial
+	into your vm guest using the command "DIAL <vmguestname>").
+	Since the line-mode major number is 212, the line to add to
+	/etc/modules.conf should be:
+		alias char-major-212 tub3270
+
+	3. Define graphic devices to your vm guest machine, if you
+	haven't already.  Define them before you reboot (reipl):
+		DEFINE GRAF 620
+		DEFINE GRAF 621
+		DEFINE GRAF 622
+		DEFINE GRAF 623
+
+	4. Reboot.  The reboot process scans hardware devices, including
+	3270s, and this enables the tub3270 driver once loaded to respond
+	correctly to the configuration requests of the next step.  If
+	you have chosen 3270 console support, your console now behaves
+	as a 3270, not a 3215.
+
+	5. Run the 3270 configuration script config3270.  It is
+	distributed in this same directory, Documentation/s390, as
+	config3270.sh.	Inspect the output script it produces,
+	/tmp/mkdev3270, and then run that script.  This will create the
+	necessary character special device files and make the necessary
+	changes to /etc/inittab.  Then notify /sbin/init that /etc/inittab
+	has changed, by issuing the telinit command with the q operand:
+		cd /usr/src/linux/Documentation/s390
+		sh config3270.sh
+		sh /tmp/mkdev3270
+		telinit q
+	This should be sufficient for your first time.	If your 3270
+	configuration has changed and you're reusing config3270, you
+	should follow these steps:
+		Change 3270 configuration
+		Reboot
+		Run config3270 and /tmp/mkdev3270
+		Reboot
+
+Here are the testing steps in detail:
+
+	1. Bring up an x3270 window, or use an actual hardware 3278 or
+	3279, or use the 3270 emulator of your choice.  You would be
+	running the emulator on your PC or workstation.  You would use
+	the command, for example,
+		x3270 vm-esa-domain-name &
+	if you wanted a 3278 Model 4 with 43 rows of 80 columns, the
+	default model number.  The driver does not take advantage of
+	extended attributes.
+
+	The screen you should now see contains a VM logo with input
+	lines near the bottom.  Use TAB to move to the bottom line,
+	probably labeled "COMMAND  ===>".
+
+	2. Use the DIAL command instead of the LOGIN command to connect
+	to one of the virtual 3270s you defined with the DEF GRAF
+	commands:
+		dial my-vm-guest-name
+
+	3. You should immediately see a login prompt from your
+	Linux-390 operating system.  If that does not happen, you would
+	see instead the line "DIALED TO my-vm-guest-name   0620".
+
+	To troubleshoot:  do these things.
+
+	A. Is the driver loaded?  Use the lsmod command (no operands)
+	to find out.  Probably it isn't.  Try loading it manually, with
+	the command "insmod tub3270".  Does that command give error
+	messages?  Ha!  There's your problem.
+
+	B. Is the /etc/inittab file modified as in installation step 3
+	above?  Use the grep command to find out; for instance, issue
+	"grep 3270 /etc/inittab".  Nothing found?  There's your
+	problem!
+
+	C. Are the device special files created, as in installation
+	step 2 above?  Use the ls -l command to find out; for instance,
+	issue "ls -l /dev/3270/tty620".  The output should start with the
+	letter "c" meaning character device and should contain "212, 1"
+	just to the left of the device name.  No such file?  no "c"?
+	Wrong major number?  Wrong minor number?  There's your
+	problem!
+
+	D. Do you get the message
+		 "HCPDIA047E my-vm-guest-name 0620 does not exist"?
+	If so, you must issue the command "DEF GRAF 620" from your VM
+	3215 console and then reboot the system.
+
+
+
+OPERATION.
+
+The driver defines three areas on the 3270 screen:  the log area, the
+input area, and the status area.
+
+The log area takes up all but the bottom two lines of the screen.  The
+driver writes terminal output to it, starting at the top line and going
+down.  When it fills, the status area changes from "Linux Running" to
+"Linux More...".  After a scrolling timeout of (default) 5 sec, the
+screen clears and more output is written, from the top down.
+
+The input area extends from the beginning of the second-to-last screen
+line to the start of the status area.  You type commands in this area
+and hit ENTER to execute them.
+
+The status area initializes to "Linux Running" to give you a warm
+fuzzy feeling.  When the log area fills up and output awaits, it
+changes to "Linux More...".  At this time you can do several things or
+nothing.  If you do nothing, the screen will clear in (default) 5 sec
+and more output will appear.  You may hit ENTER with nothing typed in
+the input area to toggle between "Linux More..." and "Linux Holding",
+which indicates no scrolling will occur.  (If you hit ENTER with "Linux
+Running" and nothing typed, the application receives a newline.)
+
+You may change the scrolling timeout value.  For example, the following
+command line:
+	echo scrolltime=60 > /proc/tty/driver/tty3270
+changes the scrolling timeout value to 60 sec.  Set scrolltime to 0 if
+you wish to prevent scrolling entirely.
+
+Other things you may do when the log area fills up are:  hit PA2 to
+clear the log area and write more output to it, or hit CLEAR to clear
+the log area and the input area and write more output to the log area.
+
+Some of the Program Function (PF) and Program Attention (PA) keys are
+preassigned special functions.  The ones that are not yield an alarm
+when pressed.
+
+PA1 causes a SIGINT to the currently running application.  You may do
+the same thing from the input area, by typing "^C" and hitting ENTER.
+
+PA2 causes the log area to be cleared.  If output awaits, it is then
+written to the log area.
+
+PF3 causes an EOF to be received as input by the application.  You may
+cause an EOF also by typing "^D" and hitting ENTER.
+
+No PF key is preassigned to cause a job suspension, but you may cause a
+job suspension by typing "^Z" and hitting ENTER.  You may wish to
+assign this function to a PF key.  To make PF7 cause job suspension,
+execute the command:
+	echo pf7=^z > /proc/tty/driver/tty3270
+
+If the input you type does not end with the two characters "^n", the
+driver appends a newline character and sends it to the tty driver;
+otherwise the driver strips the "^n" and does not append a newline.
+The IBM 3215 driver behaves similarly.
+
+Pf10 causes the most recent command to be retrieved from the tube's
+command stack (default depth 20) and displayed in the input area.  You
+may hit PF10 again for the next-most-recent command, and so on.  A
+command is entered into the stack only when the input area is not made
+invisible (such as for password entry) and it is not identical to the
+current top entry.  PF10 rotates backward through the command stack;
+PF11 rotates forward.  You may assign the backward function to any PF
+key (or PA key, for that matter), say, PA3, with the command:
+	echo -e pa3=\\033k > /proc/tty/driver/tty3270
+This assigns the string ESC-k to PA3.  Similarly, the string ESC-j
+performs the forward function.  (Rationale:  In bash with vi-mode line
+editing, ESC-k and ESC-j retrieve backward and forward history.
+Suggestions welcome.)
+
+Is a stack size of twenty commands not to your liking?  Change it on
+the fly.  To change to saving the last 100 commands, execute the
+command:
+	echo recallsize=100 > /proc/tty/driver/tty3270
+
+Have a command you issue frequently?  Assign it to a PF or PA key!  Use
+the command
+	echo pf24="mkdir foobar; cd foobar" > /proc/tty/driver/tty3270 
+to execute the commands mkdir foobar and cd foobar immediately when you
+hit PF24.  Want to see the command line first, before you execute it?
+Use the -n option of the echo command:
+	echo -n pf24="mkdir foo; cd foo" > /proc/tty/driver/tty3270
+
+
+
+Happy testing!  I welcome any and all comments about this document, the
+driver, etc etc.
+
+Dick Hitt <rbh00@utsglobal.com>
diff -u --recursive --new-file v2.4.3/linux/Documentation/s390/Debugging390.txt linux/Documentation/s390/Debugging390.txt
--- v2.4.3/linux/Documentation/s390/Debugging390.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/s390/Debugging390.txt	Thu Apr 12 12:16:35 2001
@@ -0,0 +1,2439 @@
+              
+                          Debugging on Linux for s/390 & zSeries
+			               by
+		Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+		Copyright (C) 2000-2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+                              Best viewed with fixed width fonts 
+
+Overview of Document:
+=====================
+This document is intended to give an good overview of how to debug 
+Linux for s/390 & zSeries it isn't intended as a complete reference & not a
+tutorial on the fundamentals of C & assembly, it dosen't go into
+390 IO in any detail. It is intended to compliment the documents in the
+reference section below & any other worthwhile references you get.
+
+It is intended like the Enterprise Systems Architecture/390 Reference Summary
+to be printed out & used as a quick cheat sheet self help style reference when
+problems occur.
+
+Contents
+========
+Register Set
+Address Spaces on Intel Linux
+Address Spaces on Linux for s/390 & zSeries
+The Linux for s/390 & zSeries Kernel Task Structure
+Register Usage & Stackframes on Linux for s/390 & zSeries
+A sample program with comments
+Compiling programs for debugging on Linux for s/390 & zSeries
+Figuring out gcc compile errors
+Debugging Tools
+objdump
+strace
+Performance Debugging 
+Debugging under VM
+s/390 & zSeries IO Overview
+Debugging IO on s/390 & zSeries under VM
+GDB on s/390 & zSeries
+Stack chaining in gdb by hand
+Examining core dumps
+ldd
+Debugging modules
+The proc file system
+Starting points for debugging scripting languages etc.
+Tools soon to be available
+SysRq
+References
+
+Register Set
+============
+The current architectures have the following registers.
+ 
+16  General propose registers, 32 bit on s/390 64 bit on zSeries, r0-r15 or gpr0-gpr15 used for arithmetic & addressing. 
+
+16 Control registers, 32 bit on s/390 64 bit on zSeries, ( cr0-cr15 kernel usage only ) used for memory managment,
+interrupt control,debugging control etc.
+
+16 Access registers ( ar0-ar15 ) 32 bit on s/390 & zSeries
+not used by normal programs but potentially could 
+be used as temporary storage. Their main purpose is their 1 to 1
+association with general purpose registers and are used in
+the kernel for copying data between kernel & user address spaces.
+Access register 0 ( & access register 1 on z/Series ( needs 64 bit pointer ) )
+is currently used by the pthread library as a pointer to
+the current running threads private area.
+
+16 64 bit floating point registers (fp0-fp15 ) IEEE & HFP floating 
+point format compliant on G5 upwards & a Floating point control reg (FPC) 
+4  64 bit registers (fp0,fp2,fp4 & fp6) HFP only on older machines.
+Note:
+Linux (currently) always uses IEEE & emulates G5 IEEE format on older machines,
+( provided the kernel is configured for this ).
+
+
+The PSW is the most important register on the machine it
+is 64 bit on s/390 & 128 bit on zSeries & serves the roles of 
+a program counter (pc), condition code register,memory space designator.
+In IBM standard notation I am counting bit 0 as the MSB.
+It has several advantages over a normal program counter
+in that you can change address translation & program counter 
+in a single instruction. To change address translation,
+e.g. switching address translation off requires that you
+have a logical=physical mapping for the address you are
+currently running at.
+
+      Bit           Value
+s/390 zSeries
+0       0     Reserved ( must be 0 ) otherwise specification exception occurs.
+
+1       1     Program Event Recording 1 PER enabled, 
+	      PER is used to facilititate debugging e.g. single stepping.
+
+2-4    2-4    Reserved ( must be 0 ). 
+
+5       5     Dynamic address translation 1=DAT on.
+
+6       6     Input/Output interrupt Mask
+
+7       7     External interrupt Mask used primarily for interprocessor signalling & 
+	      clock interupts.
+
+8-11  8-11    PSW Key used for complex memory protection mechanism not used under linux
+
+12      12    1 on s/390 0 on zSeries
+
+13      13    Machine Check Mask 1=enable machine check interrupts
+
+14      14    Wait State set this to 1 to stop the processor except for interrupts & give 
+	      time to other LPARS used in CPU idle in the kernel to increase overall 
+	      usage of processor resources.
+
+15      15    Problem state ( if set to 1 certain instructions are disabled )
+	      all linux user programs run with this bit 1 
+	      ( useful info for debugging under VM ).
+
+16-17 16-17   Address Space Control
+
+	      00 Primary Space Mode when DAT on
+	      The linux kernel currently runs in this mode, CR1 is affiliated with 
+              this mode & points to the primary segment table origin etc.
+
+	      01 Access register mode this mode is used in functions to 
+	      copy data between kernel & user space.
+
+	      10 Secondary space mode not used in linux however CR7 the
+	      register affiliated with this mode is & this & normally
+	      CR13=CR7 to allow us to copy data between kernel & user space.
+	      We do this as follows:
+	      We set ar2 to 0 to designate its
+	      affiliated gpr ( gpr2 )to point to primary=kernel space.
+	      We set ar4 to 1 to designate its
+	      affiliated gpr ( gpr4 ) to point to secondary=home=user space
+	      & then essentially do a memcopy(gpr2,gpr4,size) to
+	      copy data between the address spaces, the reason we use home space for the
+	      kernel & don't keep secondary space free is that code will not run in 
+	      secondary space.
+
+	      11 Home Space Mode all user programs run in this mode.
+	      it is affiliated with CR13.
+
+18-19 18-19   Condition codes (CC)
+
+20    20      Fixed point overflow mask if 1=FPU exceptions for this event 
+              occur ( normally 0 ) 
+
+21    21      Decimal overflow mask if 1=FPU exceptions for this event occur 
+              ( normally 0 )
+
+22    22      Exponent underflow mask if 1=FPU exceptions for this event occur 
+              ( normally 0 )
+
+23    23      Significance Mask if 1=FPU exceptions for this event occur 
+              ( normally 0 )
+
+24-31 24-30   Reserved Must be 0.
+
+      31      Extended Addressing Mode
+      32      Basic Addressing Mode
+              Used to set addressing mode
+	      PSW 31   PSW 32
+                0         0        24 bit
+                0         1        31 bit
+                1         1        64 bit
+
+32             1=31 bit addressing mode 0=24 bit addressing mode (for backward 
+               compatibility ), linux always runs with this bit set to 1
+
+33-64          Instruction address.
+      33-63    Reserved must be 0
+      64-127   Address
+               In 24 bits mode bits 64-103=0 bits 104-127 Address 
+               In 31 bits mode bits 64-96=0 bits 97-127 Address
+               Note: unlike 31 bit mode on s/390 bit 96 must be zero
+	       when loading the address with LPSWE otherwise a 
+               specification exception occurs, LPSW is fully backward
+               compatible.
+ 	  
+	  
+Prefix Page
+-----------	  
+This per cpu memory area is too intimately tied to the processor not to mention.
+It exists between the real addresses 0-4096 on the processor & is exchanged 
+with a page in absolute storage by the set prefix instruction in linux'es startup. 
+This page different on each processor.
+Bytes 0-512 ( 200 hex ) are used by the processor itself for holding such
+information as exception indications & entry points for exceptions.
+Bytes after 0xc00 hex are used by linux for per processor globals.
+The closest thing to this on traditional architectures is the interrupt
+vector table. This is a good thing & does simplify some of the kernel coding
+however it means that we now cannot catch stray NULL pointers in the
+kernel without hard coded checks.
+
+
+
+Address Spaces on Intel Linux
+=============================
+
+The traditional Intel Linux is approximately mapped as follows forgive
+the ascii art.
+0xFFFFFFFF 4GB Himem                        *****************
+                                            *               *
+                                            * Kernel Space  *
+                                            *               *
+                                            *****************          ****************
+User Space Himem (typically 0xC0000000 3GB )*  User Stack   *          *              *
+				            *****************          *              *
+					    *  Shared Libs  *          * Next Process *          
+                                            *****************          *     to       *  
+					    *               *    <==   *     Run      *  <==
+					    *  User Program *          *              *
+					    *   Data BSS    *          *              *
+                                            *	 Text       *          *              *
+         			            *   Sections    *          *              *
+0x00000000         			    *****************          ****************
+
+Now it is easy to see that on Intel it is quite easy to recognise a kernel address 
+as being one greater than user space himem ( in this case 0xC0000000).
+& addresses of less than this are the ones in the current running program on this
+processor ( if an smp box ).
+If using the virtual machine ( VM ) as a debugger it is quite difficult to
+know which user process is running as the address space you are looking at
+could be from any process in the run queue.
+Thankfully you normally get lucky as address spaces don't overlap that &
+you can recognise the code at by cross referencing with a dump made by objdump
+( more about that later ).
+
+The limitation of Intels addressing technique is that the linux
+kernel uses a very simple real address to virtual addressing technique
+of Real Address=Virtual Address-User Space Himem.
+This means that on Intel the kernel linux can typically only address
+Himem=0xFFFFFFFF-0xC0000000=1GB & this is all the RAM these machines
+can typically use.
+They can lower User Himem to 2GB or lower & thus be
+able to use 2GB of RAM however this shrinks the maximum size
+of User Space from 3GB to 2GB they have a no win limit of 4GB unless
+they go to 64 Bit.
+
+
+On 390 our limitations & strengths make us slightly different.
+For backward compatibility we are only allowed use 31 bits (2GB)
+of our 32 bit addresses,however, we use entirely separate address 
+spaces for the user & kernel.
+
+This means we can support 2GB of non Extended RAM, & more
+with the Extended memory managment swap device & 64 Bit
+when it comes along.
+
+
+Address Spaces on Linux for S390
+================================
+
+Our addressing scheme is as follows
+
+
+Himem 0x7fffffff 2GB on s/390   *****************          ****************
+2^64 bytes on zSeries           *  User Stack   *          *              *
+				*****************          *              *
+		                *  Shared Libs  *          *              *          
+                                *****************          *              *  
+			        *               *          *    Kernel    *  
+		                *  User Program *          *              *
+		                *   Data BSS    *          *              *
+                                *    Text       *          *              *
+            			*   Sections    *          *              *
+0x00000000                      *****************          ****************
+
+This also means that we need to look at the PSW problem state bit
+or the addressing mode to decide whether we are looking at
+user or kernel space. 
+
+The Linux for s/390 & zSeries Kernel Task Structure
+===================================================
+Each process/thread under Linux for S390 has its own kernel task_struct
+defined in linux/include/linux/sched.h
+The S390 on initialisation & resuming of a process on a cpu sets
+the __LC_KERNEL_STACK variable in the spare prefix area for this cpu
+( which we use for per processor globals).
+
+The kernel stack pointer is intimately tied with the task stucture for
+each processor as follows.
+
+                      s/390
+            ************************
+            *  1 page kernel stack *
+	    *        ( 4K )        *
+            ************************
+            *   1 page task_struct *        
+            *        ( 4K )        *
+8K aligned  ************************ 
+
+                     zSeries
+            ************************
+            *  2 page kernel stack *
+	    *        ( 8K )        *
+            ************************
+            *  2 page task_struct  *        
+            *        ( 8K )        *
+16K aligned ************************ 
+
+What this means is that we don't need to dedicate any register or global variable
+to point to the current running process & can retrieve it with the following
+very simple construct for s/390 & one very similar for zSeries.
+
+static inline struct task_struct * get_current(void)
+{
+        struct task_struct *current;
+        __asm__("lhi   %0,-8192\n\t"
+                "nr    %0,15"
+                : "=r" (current) );
+        return current;
+}
+
+i.e. just anding the current kernel stack pointer with the mask -8192.
+Thankfully because Linux dosen't have support for nested IO interrupts
+& our devices have large buffers can survive interrupts being shut for 
+short amounts of time we don't need a separate stack for interrupts.
+
+
+
+
+Register Usage & Stackframes on Linux for s/390 & zSeries
+=========================================================
+Overview:
+---------
+This is the code that gcc produces at the top & the bottom of
+each function, it usually is fairly consistent & similar from 
+function to function & if you know its layout you can probalby
+make some headway in finding the ultimate cause of a problem
+after a crash without a source level debugger.
+
+Note: To follow stackframes requires a knowledge of C or Pascal &
+limited knowledge of one assembly language.
+
+It should be noted that there are some differences between the
+s/390 & zSeries stack layouts as the zSeries stack layout didn't have
+to maintain compatibility with older linkage formats.
+
+Glossary:
+---------
+alloca:
+This is a built in compiler function for runtime allocation
+of extra space on the callers stack which is obviously freed
+up on function exit ( e.g. the caller may choose to allocate nothing
+of a buffer of 4k if required for temporary purposes ), it generates 
+very efficent code ( a few cycles  ) when compared to alternatives 
+like malloc.
+
+automatics: These are local variables on the stack,
+i.e they aren't in registers & they aren't static.
+
+back-chain:
+This is a pointer to the stack pointer before entering a
+framed functions ( see frameless function ) prologue got by 
+deferencing the address of the current stack pointer,
+ i.e. got by accessing the 32 bit value at the stack pointers
+current location.
+
+base-pointer:
+This is a pointer to the back of the literal pool which
+is an area just behind each procedure used to store constants
+in each function.
+
+call-clobbered: The caller probably needs to save these registers if there 
+is something of value in them, on the stack or elsewhere before making a 
+call to another procedure so that it can restore it later.
+
+epilogue:
+The code generated by the compiler to return to the caller.
+
+frameless-function
+A frameless function in Linux for s390 & zSeries is one which doesn't need 
+more than the register save area ( 96 bytes on s/390, 160 on zSeries )
+given to it by the caller.
+A frameless function never:
+1) Sets up a back chain.
+2) Calls alloca.
+3) Calls other normal functions
+4) Has automatics.
+
+GOT-pointer:
+This is a pointer to the global-offset-table in ELF
+( Executable Linkable Format, Linux'es most common executable format ),
+all globals & shared library objects are found using this pointer.
+
+lazy-binding
+ELF shared libraries are typically only loaded when routines in the shared
+library are actually first called at runtime. This is lazy binding.
+
+procedure-linkage-table
+This is a table found from the GOT which contains pointers to routines
+in other shared libraries which can't be called to by easier means.
+
+prologue:
+The code generated by the compiler to set up the stack frame.
+
+outgoing-args:
+This is extra area allocated on the stack of the calling function if the
+parameters for the callee's cannot all be put in registers, the same
+area can be reused by each function the caller calls.
+
+routine-descriptor:
+A COFF  executable format based concept of a procedure reference 
+actually being 8 bytes or more as opposed to a simple pointer to the routine.
+This is typically defined as follows
+Routine Descriptor offset 0=Pointer to Function
+Routine Descriptor offset 4=Pointer to Table of Contents
+The table of contents/TOC is roughly equivalent to a GOT pointer.
+& it means that shared libraries etc. can be shared between several
+environments each with their own TOC.
+
+ 
+static-chain: This is used in nested functions a concept adopted from pascal 
+by gcc not used in ansi C or C++ ( although quite useful ), basically it
+is a pointer used to reference local variables of enclosing functions.
+You might come across this stuff once or twice in your lifetime.
+
+e.g.
+The function below should return 11 though gcc may get upset & toss warnings 
+about unused variables.
+int FunctionA(int a)
+{
+	int b;
+	FunctionC(int c)
+	{
+		b=c+1;
+	}
+	FunctionC(10);
+	return(b);
+}
+
+
+s/390 & zSeries Register usage
+==============================
+r0       used by syscalls/assembly                  call-clobbered
+r1	 used by syscalls/assembly                  call-clobbered
+r2       argument 0 / return value 0                call-clobbered
+r3       argument 1 / return value 1 (if long long) call-clobbered
+r4       argument 2                                 call-clobbered
+r5       argument 3                                 call-clobbered
+r6	 argument 5                                 saved
+r7       pointer-to arguments 5 to ...              saved      
+r8       this & that                                saved
+r9       this & that                                saved
+r10      static-chain ( if nested function )        saved
+r11      frame-pointer ( if function used alloca )  saved
+r12      got-pointer                                saved
+r13      base-pointer                               saved
+r14      return-address                             saved
+r15      stack-pointer                              saved
+
+f0       argument 0 / return value ( float/double ) call-clobbered
+f2       argument 1                                 call-clobbered
+f4       zSeries argument 2                           saved
+f6       zSeries argument 3                           saved
+The remaining floating points
+f1,f3,f5 f7-f15 are call-clobbered.
+
+Notes:
+------
+1) The only requirement is that registers which are used
+by the callee are saved, e.g. the compiler is perfectly
+capible of using r11 for purposes other than a frame a
+frame pointer if a frame pointer is not needed.
+2) In functions with variable arguments e.g. printf the calling procedure 
+is identical to one without variable arguments & the same number of 
+parameters. However, the prologue of this function is somewhat more
+hairy owing to it having to move these parameters to the stack to
+get va_start, va_arg & va_end to work.
+3) Access registers are currently unused by gcc but are used in
+the kernel. Possibilities exist to use them at the moment for
+temporary storage but it isn't recommended.
+4) Only 4 of the floating point registers are used for
+parameter passing as older machines such as G3 only have only 4
+& it keeps the stack frame compatible with other compilers.
+However with IEEE floating point emulation under linux on the
+older machines you are free to use the other 12.
+5) A long long or double parameter cannot be have the 
+first 4 bytes in a register & the second four bytes in the 
+outgoing args area. It must be purely in the outgoing args
+area if crossing this boundary.
+6) Floating point parameters are mixed with outgoing args
+on the outgoing args area in the order the are passed in as parameters.
+7) Floating point arguments 2 & 3 are saved in the outgoing args area for zSeries
+
+
+Stack Frame Layout
+------------------
+s/390     zSeries
+0         0             back chain ( a 0 here signifies end of back chain )
+4         8             eos ( end of stack, not used on Linux for S390 used in other linkage formats )
+8         16            glue used in other s/390 linkage formats for saved routine descriptors etc.
+12        24            glue used in other s/390 linkage formats for saved routine descriptors etc.
+16        32            scratch area
+20        40            scratch area
+24        48            saved r6 of caller function
+28        56            saved r7 of caller function
+32        64            saved r8 of caller function
+36        72            saved r9 of caller function
+40        80            saved r10 of caller function
+44        88            saved r11 of caller function
+48        96            saved r12 of caller function
+52        104           saved r13 of caller function
+56        112           saved r14 of caller function
+60        120           saved r15 of caller function
+64        128           saved f4 of caller function
+72        132           saved f6 of caller function
+80                      undefined
+96        160           outgoing args passed from caller to callee
+96+x      160+x         possible stack alignment ( 8 bytes desirable )
+96+x+y    160+x+y       alloca space of caller ( if used )
+96+x+y+z  160+x+y+z     automatics of caller ( if used )
+0                       back-chain
+
+A sample program with comments.
+===============================
+
+Comments on the function test
+-----------------------------
+1) It didn't need to set up a pointer to the constant pool gpr13 as it isn't used
+( :-( ).
+2) This is a frameless function & no stack is bought.
+3) The compiler was clever enough to recognise that it could return the
+value in r2 as well as use it for the passed in parameter ( :-) ).
+4) The basr ( branch relative & save ) trick works as follows the instruction 
+has a special case with r0,r0 with some instruction operands is understood as 
+the literal value 0, some risc architectures also do this ). So now
+we are branching to the next address & the address new program counter is
+in r13,so now we subtract the size of the function prologue we have executed
++ the size of the literal pool to get to the top of the literal pool
+0040037c int test(int b)
+{                                                          # Function prologue below
+  40037c:	90 de f0 34 	stm	%r13,%r14,52(%r15) # Save registers r13 & r14
+  400380:	0d d0       	basr	%r13,%r0           # Set up pointer to constant pool using
+  400382:	a7 da ff fa 	ahi	%r13,-6            # basr trick
+	return(5+b);
+	                                                   # Huge main program
+  400386:	a7 2a 00 05 	ahi	%r2,5              # add 5 to r2
+
+                                                           # Function epilogue below 
+  40038a:	98 de f0 34 	lm	%r13,%r14,52(%r15) # restore registers r13 & 14
+  40038e:	07 fe       	br	%r14               # return
+}
+
+Comments on the function main
+-----------------------------
+1) The compiler did this function optimally ( 8-) )
+
+Literal pool for main.
+400390:	ff ff ff ec 	.long 0xffffffec
+main(int argc,char *argv[])
+{                                                          # Function prologue below
+  400394:	90 bf f0 2c 	stm	%r11,%r15,44(%r15) # Save necessary registers
+  400398:	18 0f       	lr	%r0,%r15           # copy stack pointer to r0
+  40039a:	a7 fa ff a0 	ahi	%r15,-96           # Make area for callee saving 
+  40039e:	0d d0       	basr	%r13,%r0           # Set up r13 to point to
+  4003a0:	a7 da ff f0 	ahi	%r13,-16           # literal pool
+  4003a4:	50 00 f0 00 	st	%r0,0(%r15)        # Save backchain
+
+	return(test(5));                                   # Main Program Below
+  4003a8:	58 e0 d0 00 	l	%r14,0(%r13)       # load relative address of test from
+						           # literal pool
+  4003ac:	a7 28 00 05 	lhi	%r2,5              # Set first parameter to 5
+  4003b0:	4d ee d0 00 	bas	%r14,0(%r14,%r13)  # jump to test setting r14 as return
+							   # address using branch & save instruction.
+
+							   # Function Epilogue below
+  4003b4:	98 bf f0 8c 	lm	%r11,%r15,140(%r15)# Restore necessary registers.
+  4003b8:	07 fe       	br	%r14               # return to do program exit 
+}
+
+
+Compiler updates
+----------------
+
+main(int argc,char *argv[])
+{
+  4004fc:	90 7f f0 1c       	stm	%r7,%r15,28(%r15)
+  400500:	a7 d5 00 04       	bras	%r13,400508 <main+0xc>
+  400504:	00 40 04 f4       	.long	0x004004f4 
+  # compiler now puts constant pool in code to so it saves an instruction 
+  400508:	18 0f             	lr	%r0,%r15
+  40050a:	a7 fa ff a0       	ahi	%r15,-96
+  40050e:	50 00 f0 00       	st	%r0,0(%r15)
+	return(test(5));
+  400512:	58 10 d0 00       	l	%r1,0(%r13)
+  400516:	a7 28 00 05       	lhi	%r2,5
+  40051a:	0d e1             	basr	%r14,%r1
+  # compiler adds 1 extra instruction to epilogue this is done to
+  # avoid processor pipeline stalls owing to data dependencies on g5 &
+  # above as register 14 in the old code was needed directly after being loaded 
+  # by the lm	%r11,%r15,140(%r15) for the br %14.
+  40051c:	58 40 f0 98       	l	%r4,152(%r15)
+  400520:	98 7f f0 7c       	lm	%r7,%r15,124(%r15)
+  400524:	07 f4             	br	%r4
+}
+
+
+Hartmut ( our compiler developer ) also has been threatening to take out the
+stack backchain in optimised code as this also causes pipeline stalls, you
+have been warned.
+
+64 bit zSeries code disassembly
+-------------------------------
+
+If you understand the stuff above you'll understand the stuff
+below too so I'll avoid repeating myself & just say that 
+some of the instructions have g's on the end of them to indicate
+they are 64 bit & the stack offsets are a bigger, 
+the only other difference you'll find between 32 & 64 bit is that
+we now use f4 & f6 for floating point arguments on 64 bit.
+00000000800005b0 <test>:
+int test(int b)
+{
+	return(5+b);
+    800005b0:	a7 2a 00 05       	ahi	%r2,5
+    800005b4:	b9 14 00 22       	lgfr	%r2,%r2 # downcast to integer
+    800005b8:	07 fe             	br	%r14
+    800005ba:	07 07             	bcr	0,%r7
+
+
+}
+
+00000000800005bc <main>:
+main(int argc,char *argv[])
+{ 
+    800005bc:	eb bf f0 58 00 24 	stmg	%r11,%r15,88(%r15)
+    800005c2:	b9 04 00 1f       	lgr	%r1,%r15
+    800005c6:	a7 fb ff 60       	aghi	%r15,-160
+    800005ca:	e3 10 f0 00 00 24 	stg	%r1,0(%r15)
+	return(test(5));
+    800005d0:	a7 29 00 05       	lghi	%r2,5
+    # brasl allows jumps > 64k & is overkill here bras would do fune
+    800005d4:	c0 e5 ff ff ff ee 	brasl	%r14,800005b0 <test> 
+    800005da:	e3 40 f1 10 00 04 	lg	%r4,272(%r15)
+    800005e0:	eb bf f0 f8 00 04 	lmg	%r11,%r15,248(%r15)
+    800005e6:	07 f4             	br	%r4
+}
+
+
+
+Compiling programs for debugging on Linux for s/390 & zSeries
+=============================================================
+-gdwarf2 now works & normal -g debugging works much better now
+Thanks to the IBM java compiler developers bug reports. 
+
+This is typically done adding/appending the flags -g to the 
+CFLAGS & LDFLAGS variables Makefile of the program concerned.
+
+If using gdb & you would like accurate displays of registers &
+ stack traces compile without optimisation i.e make sure
+that there is no -O2 or similar on the CFLAGS line of the Makefile &
+the emitted gcc commands, obviously this will produce worse code 
+( not advisable for shipment ) but it is an  aid to the debugging process.
+
+This aids debugging because the compiler will copy parameters passed in
+in registers onto the stack so backtracing & looking at passed in
+parameters will work, however some larger programs which use inline functions
+will not compile without optimisation.
+
+Debugging with optimisation has since much improved after fixing
+some bugs, please make sure you are using gdb-5.0 or later developed 
+after Nov'2000.
+
+Figuring out gcc compile errors
+===============================
+If you are getting a lot of syntax errors compiling a program & the problem
+isn't blatantly obvious from the source.
+It often helps to just preprocess the file, this is done with the -E
+option in gcc.
+What this does is that it runs through the very first phase of compilation
+( compilation in gcc is done in several stages & gcc calls many programs to
+achieve its end result ) with the -E option gcc just calls the gcc preprocessor (cpp).
+The c preprocessor does the following, it joins all the files #included together
+recursively ( #include files can #include other files ) & also the c file you wish to compile.
+It puts a fully qualified path of the #included files in a comment & it
+does macro expansion.
+This is useful for debugging because
+1) You can double check whether the files you expect to be included are the ones
+that are being included ( e.g. double check that you aren't going to the i386 asm directory ).
+2) Check that macro definitions aren't clashing with typedefs,
+3) Check that definitons aren't being used before they are being included.
+4) Helps put the line emitting the error under the microscope if it contains macros.
+
+For convenience the Linux kernel's makefile will do preprocessing automatically for you
+by suffixing the file you want built with .i ( instead of .o )
+
+e.g.
+from the linux directory type
+make arch/s390/kernel/signal.i
+this will build
+
+s390-gcc -D__KERNEL__ -I/home1/barrow/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+-fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce   -E arch/s390/kernel/signal.c
+> arch/s390/kernel/signal.i  
+
+Now look at signal.i you should see something like.
+
+
+# 1 "/home1/barrow/linux/include/asm/types.h" 1
+typedef unsigned short umode_t;
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+If instead you are getting errors further down e.g.
+unknown instruction:2515 "move.l" or better still unknown instruction:2515 
+"Fixme not implemented yet, call Martin" you are probably are attempting to compile some code 
+meant for another architecture or code that is simply not implemented, with a fixme statement
+stuck into the inline assembly code so that the author of the file now knows he has work to do.
+To look at the assembly emitted by gcc just before it is about to call gas ( the gnu assembler )
+use the -S option.
+Again for your convenience the Linux kernel's Makefile will hold your hand &
+do all this donkey work for you also by building the file with the .s suffix.
+e.g.
+from the Linux directory type 
+make arch/s390/kernel/signal.s 
+
+s390-gcc -D__KERNEL__ -I/home1/barrow/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+-fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce  -S arch/s390/kernel/signal.c 
+-o arch/s390/kernel/signal.s  
+
+
+This will output something like, ( please note the constant pool & the useful comments
+in the prologue to give you a hand at interpreting it ).
+
+.LC54:
+	.string	"misaligned (__u16 *) in __xchg\n"
+.LC57:
+	.string	"misaligned (__u32 *) in __xchg\n"
+.L$PG1: # Pool sys_sigsuspend
+.LC192:
+	.long	-262401
+.LC193:
+	.long	-1
+.LC194:
+	.long	schedule-.L$PG1
+.LC195:
+	.long	do_signal-.L$PG1
+	.align 4
+.globl sys_sigsuspend
+	.type	 sys_sigsuspend,@function
+sys_sigsuspend:
+#	leaf function           0
+#	automatics              16
+#	outgoing args           0
+#	need frame pointer      0
+#	call alloca             0
+#	has varargs             0
+#	incoming args (stack)   0
+#	function length         168
+	STM	8,15,32(15)
+	LR	0,15
+	AHI	15,-112
+	BASR	13,0
+.L$CO1:	AHI	13,.L$PG1-.L$CO1
+	ST	0,0(15)
+	LR    8,2
+	N     5,.LC192-.L$PG1(13) 
+
+Adding -g to the above output makes the output even more useful
+e.g. typing
+make CC:="s390-gcc -g" kernel/sched.s
+
+which compiles.
+s390-gcc -g -D__KERNEL__ -I/home/barrow/linux-2.3/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce   -S kernel/sched.c -o kernel/sched.s 
+
+also outputs stabs ( debugger ) info, from this info you can find out the
+offsets & sizes of various elements in structures.
+e.g. the stab for the structure
+struct rlimit {
+	unsigned long	rlim_cur;
+	unsigned long	rlim_max;
+};
+is
+.stabs "rlimit:T(151,2)=s8rlim_cur:(0,5),0,32;rlim_max:(0,5),32,32;;",128,0,0,0
+from this stab you can see that 
+rlimit_cur starts at bit offset 0 & is 32 bits in size
+rlimit_max starts at bit offset 32 & is 32 bits in size.
+
+
+Debugging Tools:
+================
+
+objdump
+=======
+This is a tool with many options the most useful being ( if compiled with -g).
+objdump --source <victim program or object file> > <victims debug listing >
+
+
+The whole kernel can be compiled like this ( Doing this will make a 17MB kernel
+& a 200 MB listing ) however you have to strip it before building the image
+using the strip command to make it a more reasonable size to boot it.
+
+A source/assembly mixed dump of the kernel can be done with the line
+objdump --source vmlinux > vmlinux.lst
+Also if the file isn't compiled -g this will output as much debugging information
+as it can ( e.g. function names ), however, this is very slow as it spends lots
+of time searching for debugging info, the following self explanitory line should be used 
+instead if the code isn't compiled -g.
+objdump --disassemble-all --syms vmlinux > vmlinux.lst  
+as it is much faster
+
+As hard drive space is valuble most of us use the following approach.
+1) Look at the emitted psw on the console to find the crash address in the kernel.
+2) Look at the file System.map ( in the linux directory ) produced when building 
+the kernel to find the closest address less than the current PSW to find the
+offending function.
+3) use grep or similar to search the source tree looking for the source file
+ with this function if you don't know where it is.
+4) rebuild this object file with -g on, as an example suppose the file was
+( /arch/s390/kernel/signal.o ) 
+5) Assuming the file with the erroneous function is signal.c Move to the base of the 
+Linux source tree.
+6) rm /arch/s390/kernel/signal.o
+7) make /arch/s390/kernel/signal.o
+8) watch the gcc command line emitted
+9) type it in again or alernatively cut & paste it on the console adding the -g option.
+10) objdump --source arch/s390/kernel/signal.o > signal.lst
+This will output the source & the assembly intermixed, as the snippet below shows
+This will unfortunately output addresses which aren't the same
+as the kernel ones you should be able to get around the mental arithmetic
+by playing with the --adjust-vma parameter to objdump.
+
+
+
+
+extern inline void spin_lock(spinlock_t *lp)
+{
+      a0:       18 34           lr      %r3,%r4
+      a2:       a7 3a 03 bc     ahi     %r3,956
+        __asm__ __volatile("    lhi   1,-1\n"
+      a6:       a7 18 ff ff     lhi     %r1,-1
+      aa:       1f 00           slr     %r0,%r0
+      ac:       ba 01 30 00     cs      %r0,%r1,0(%r3)
+      b0:       a7 44 ff fd     jm      aa <sys_sigsuspend+0x2e>
+        saveset = current->blocked;
+      b4:       d2 07 f0 68     mvc     104(8,%r15),972(%r4)
+      b8:       43 cc
+        return (set->sig[0] & mask) != 0;
+} 
+
+6) If debugging under VM go down to that section in the document for more info.
+
+
+I now have a tool which takes the pain out of --adjust-vma
+& you are able to do something like
+make /arch/s390/kernel/traps.lst
+& it automatically generates the correctly relocated entries for
+the text segment in traps.lst.
+This tool is now standard in linux distro's in scripts/makelst
+
+strace:
+-------
+Q. What is it ?
+A. It is a tool for intercepting calls to the kernel & logging them
+to a file & on the screen.
+
+Q. What use is it ?
+A. You can used it to find out what files a particular program opens.
+
+
+
+Example 1
+---------
+If you wanted to know does ping work but didn't have the source 
+strace ping -c 1 127.0.0.1  
+& then look at the man pages for each of the syscalls below,
+( In fact this is sometimes easier than looking at some spagetti
+source which conditionally compiles for several architectures )
+Not everything that it throws out needs to make sense immeadiately
+
+Just looking quickly you can see that it is making up a RAW socket
+for the ICMP protocol.
+Doing an alarm(10) for a 10 second timeout
+& doing a gettimeofday call before & after each read to see 
+how long the replies took, & writing some text to stdout so the user
+has an idea what is going on.
+
+socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
+getuid()                                = 0
+setuid(0)                               = 0
+stat("/usr/share/locale/C/libc.cat", 0xbffff134) = -1 ENOENT (No such file or directory)
+stat("/usr/share/locale/libc/C", 0xbffff134) = -1 ENOENT (No such file or directory)
+stat("/usr/local/share/locale/C/libc.cat", 0xbffff134) = -1 ENOENT (No such file or directory)
+getpid()                                = 353
+setsockopt(3, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
+setsockopt(3, SOL_SOCKET, SO_RCVBUF, [49152], 4) = 0
+fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(3, 1), ...}) = 0
+mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40008000
+ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0
+write(1, "PING 127.0.0.1 (127.0.0.1): 56 d"..., 42PING 127.0.0.1 (127.0.0.1): 56 data bytes
+) = 42
+sigaction(SIGINT, {0x8049ba0, [], SA_RESTART}, {SIG_DFL}) = 0 
+sigaction(SIGALRM, {0x8049600, [], SA_RESTART}, {SIG_DFL}) = 0
+gettimeofday({948904719, 138951}, NULL) = 0
+sendto(3, "\10\0D\201a\1\0\0\17#\2178\307\36"..., 64, 0, {sin_family=AF_INET,
+sin_port=htons(0), sin_addr=inet_addr("127.0.0.1")}, 16) = 64
+sigaction(SIGALRM, {0x8049600, [], SA_RESTART}, {0x8049600, [], SA_RESTART}) = 0
+sigaction(SIGALRM, {0x8049ba0, [], SA_RESTART}, {0x8049600, [], SA_RESTART}) = 0
+alarm(10)                               = 0
+recvfrom(3, "E\0\0T\0005\0\0@\1|r\177\0\0\1\177"..., 192, 0, 
+{sin_family=AF_INET, sin_port=htons(50882), sin_addr=inet_addr("127.0.0.1")}, [16]) = 84
+gettimeofday({948904719, 160224}, NULL) = 0
+recvfrom(3, "E\0\0T\0006\0\0\377\1\275p\177\0"..., 192, 0, 
+{sin_family=AF_INET, sin_port=htons(50882), sin_addr=inet_addr("127.0.0.1")}, [16]) = 84
+gettimeofday({948904719, 166952}, NULL) = 0
+write(1, "64 bytes from 127.0.0.1: icmp_se"..., 
+5764 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=28.0 ms
+
+Example 2
+---------
+strace passwd 2>&1 | grep open
+produces the following output
+open("/etc/ld.so.cache", O_RDONLY)      = 3
+open("/opt/kde/lib/libc.so.5", O_RDONLY) = -1 ENOENT (No such file or directory)
+open("/lib/libc.so.5", O_RDONLY)        = 3
+open("/dev", O_RDONLY)                  = 3
+open("/var/run/utmp", O_RDONLY)         = 3
+open("/etc/passwd", O_RDONLY)           = 3
+open("/etc/shadow", O_RDONLY)           = 3
+open("/etc/login.defs", O_RDONLY)       = 4
+open("/dev/tty", O_RDONLY)              = 4 
+
+The 2>&1 is done to redirect stderr to stdout & grep is then filtering this input 
+through the pipe for each line containing the string open.
+
+
+Example 3
+---------
+Getting sophistocated
+telnetd crashes on & I don't know why
+Steps
+-----
+1) Replace the following line in /etc/inetd.conf
+telnet  stream  tcp     nowait  root    /usr/sbin/in.telnetd -h 
+with
+telnet  stream  tcp     nowait  root    /blah
+
+2) Create the file /blah with the following contents to start tracing telnetd 
+#!/bin/bash
+/usr/bin/strace -o/t1 -f /usr/sbin/in.telnetd -h 
+3) chmod 700 /blah to make it executable only to root
+4)
+killall -HUP inetd
+or ps aux | grep inetd
+get inetd's process id
+& kill -HUP inetd to restart it.
+
+Important options
+-----------------
+-o is used to tell strace to output to a file in our case t1 in the root directory
+-f is to follow children i.e.
+e.g in our case above telnetd will start the login process & subsequently a shell like bash.
+You will be able to tell which is which from the process ID's listed on the left hand side
+of the strace output.
+-p<pid> will tell strace to attach to a running process, yup this can be done provided
+ it isn't being traced or debugged already & you have enough privileges,
+the reason 2 processes cannot trace or debug the same program is that strace
+becomes the parent process of the one being debugged & processes ( unlike people )
+can have only one parent.
+
+
+However the file /t1 will get big quite quickly
+to test it telnet 127.0.0.1
+
+now look at what files in.telnetd execve'd
+413   execve("/usr/sbin/in.telnetd", ["/usr/sbin/in.telnetd", "-h"], [/* 17 vars */]) = 0
+414   execve("/bin/login", ["/bin/login", "-h", "localhost", "-p"], [/* 2 vars */]) = 0 
+
+Whey it worked!.
+
+
+Other hints:
+------------
+If the program is not very interactive ( i.e. not much keyboard input )
+& is crashing in one architecture but not in another you can do 
+an strace of both programs under as identical a scenario as you can
+on both architectures outputting to a file then.
+do a diff of the two traces using the diff program
+i.e.
+diff output1 output2
+& maybe you'll be able to see where the call paths differed, this
+is possibly near the cause of the crash. 
+
+More info
+---------
+Look at man pages for strace & the various syscalls
+e.g. man strace, man alarm, man socket.
+
+
+Performance Debugging
+=====================
+gcc is capible of compiling in profiling code just add the -p option
+to the CFLAGS, this obviously affects program size & performance.
+This can be used by the gprof gnu profiling tool or the
+gcov the gnu code coverage tool ( code coverage is a means of testing
+code quality by checking if all the code in an executable in exercised by
+a tester ).
+
+
+Using top to find out where processes are sleeping in the kernel
+----------------------------------------------------------------
+To do this copy the System.map from the root directory where
+the linux kernel was built to the /boot directory on your 
+linux machine.
+Start top
+Now type fU<return>
+You should see a new field called WCHAN which
+tells you where each process is sleeping here is a typical output.
+ 
+ 6:59pm  up 41 min,  1 user,  load average: 0.00, 0.00, 0.00
+28 processes: 27 sleeping, 1 running, 0 zombie, 0 stopped
+CPU states:  0.0% user,  0.1% system,  0.0% nice, 99.8% idle
+Mem:   254900K av,   45976K used,  208924K free,       0K shrd,   28636K buff
+Swap:       0K av,       0K used,       0K free                    8620K cached
+
+  PID USER     PRI  NI  SIZE  RSS SHARE WCHAN     STAT  LIB %CPU %MEM   TIME COMMAND
+  750 root      12   0   848  848   700 do_select S       0  0.1  0.3   0:00 in.telnetd
+  767 root      16   0  1140 1140   964           R       0  0.1  0.4   0:00 top
+    1 root       8   0   212  212   180 do_select S       0  0.0  0.0   0:00 init
+    2 root       9   0     0    0     0 down_inte SW      0  0.0  0.0   0:00 kmcheck
+
+The time command
+----------------
+Another related command is the time command which gives you an indication
+of where a process is spending the majority of its time.
+e.g.
+time ping -c 5 nc
+outputs
+real	0m4.054s
+user	0m0.010s
+sys	0m0.010s
+
+Debugging under VM
+==================
+
+Notes
+-----
+Addresses & values in the VM debugger are always hex never decimal
+Address ranges are of the format <HexValue1>-<HexValue2> or <HexValue1>.<HexValue2> 
+e.g. The address range  0x2000 to 0x3000 can be described described as
+2000-3000 or 2000.1000
+
+The VM Debugger is case insensitive.
+
+VM's strengths are usually other debuggers weaknesses you can get at any resource
+no matter how sensitive e.g. memory managment resources,change address translation
+in the PSW. For kernel hacking you will reap dividends if you get good at it.
+
+The VM Debugger displays operators but not operands, probably because some
+of it was written when memory was expensive & the programmer was probably proud that
+it fitted into 2k of memory & the programmers & didn't want to shock hardcore VM'ers by
+changing the interface :-), also the debugger displays useful information on the same line & 
+the author of the code probably felt that it was a good idea not to go over 
+the 80 columns on the screen. 
+
+As some of you are probably in a panic now this isn't as unintuitive as it may seem
+as the 390 instructions are easy to decode mentally & you can make a good guess at a lot 
+of them as all the operands are nibble ( half byte aligned ) & if you have an objdump listing
+also it is quite easy to follow, if you don't have an objdump listing keep a copy of
+the s/390 Reference Summary & look at between pages 2 & 7 or alternatively the
+s/390 principles of operation.
+e.g. even I can guess that 
+0001AFF8' LR    180F        CC 0
+is a ( load register ) lr r0,r15 
+
+Also it is very easy to tell the length of a 390 instruction from the 2 most significant
+bits in the instruction ( not that this info is really useful except if you are trying to
+make sense of a hexdump of code ).
+Here is a table
+Bits                    Instruction Length
+------------------------------------------
+00                          2 Bytes
+01                          4 Bytes
+10                          4 Bytes
+11                          6 Bytes
+
+
+
+
+The debugger also displays other useful info on the same line such as the
+addresses being operated on destination addresses of branches & condition codes.
+e.g.  
+00019736' AHI   A7DAFF0E    CC 1
+000198BA' BRC   A7840004 -> 000198C2'   CC 0
+000198CE' STM   900EF068 >> 0FA95E78    CC 2
+
+
+
+Useful VM debugger commands
+---------------------------
+
+I suppose I'd better mention this before I start
+to list the current active traces do 
+Q TR
+there can be a maximum of 255 of these per set
+( more about trace sets later ).
+To stop traces issue a
+TR END.
+To delete a particular breakpoint issue
+TR DEL <breakpoint number>
+
+The PA1 key drops to CP mode so you can issue debugger commands,
+Doing alt c (on my 3270 console at least ) clears the screen. 
+hitting b <enter> comes back to the running operating system
+from cp mode ( in our case linux ).
+It is typically useful to add shortcuts to your profile.exec file
+if you have one ( this is roughly equivalent to autoexec.bat in DOS ).
+file here are a few from mine.
+/* this gives me command history on issuing f12 */
+set pf12 retrieve 
+/* this continues */
+set pf8 imm b
+/* goes to trace set a */
+set pf1 imm tr goto a
+/* goes to trace set b */
+set pf2 imm tr goto b
+/* goes to trace set c */
+set pf3 imm tr goto c
+
+
+
+Instruction Tracing
+-------------------
+Setting a simple breakpoint
+TR I PSWA <address>
+To debug a particular function try
+TR I R <function address range>
+TR I on its own will single step.
+TR I DATA <MNEMONIC> <OPTIONAL RANGE> will trace for particular mnemonics
+e.g.
+TR I DATA 4D R 0197BC.4000
+will trace for BAS'es ( opcode 4D ) in the range 0197BC.4000
+if you were inclined you could add traces for all branch instructions &
+suffix them with the run prefix so you would have a backtrace on screen 
+when a program crashes.
+TR BR <INTO OR FROM> will trace branches into or out of an address.
+e.g.
+TR BR INTO 0 is often quite useful if a program is getting awkward & deciding
+to branch to 0 & crashing as this will stop at the address before in jumps to 0.
+TR I R <address range> RUN cmd d g
+single steps a range of addresses but stays running &
+displays the gprs on each step.
+
+
+
+Displaying & modifying Registers
+--------------------------------
+D G will display all the gprs
+Adding a extra G to all the commands is neccessary to access the full 64 bit 
+content in VM on zSeries obviously this isn't required for access registers
+as these are still 32 bit.
+e.g. DGG instead of DG 
+D X will display all the control registers
+D AR will display all the access registers
+D AR4-7 will display access registers 4 to 7
+CPU ALL D G will display the GRPS of all CPUS in the configuration
+D PSW will display the current PSW
+st PSW 2000 will put the value 2000 into the PSW &
+cause crash your machine.
+D PREFIX displays the prefix offset
+
+
+Displaying Memory
+-----------------
+To display memory mapped using the current PSW's mapping try
+D <range>
+To make VM display a message each time it hits a particular address & continue try
+D I<range> will disassemble/display a range of instructions.
+ST addr 32 bit word will store a 32 bit aligned address
+D T<range> will display the EBCDIC in an address ( if you are that way inclined )
+D R<range> will display real addresses ( without DAT ) but with prefixing.
+There are other complex options to display if you need to get at say home space
+but are in primary space the easiest thing to do is to temporarily
+modify the PSW to the other addressing mode, display the stuff & then
+restore it.
+
+
+ 
+Hints
+-----
+If you want to issue a debugger command without halting your virtual machine with the
+PA1 key try prefixing the command with #CP e.g.
+#cp tr i pswa 2000
+also suffixing most debugger commands with RUN will cause them not
+to stop just display the mnemonic at the current instruction on the console.
+If you have several breakpoints you want to put into your program &
+you get fed up of cross referencing with System.map
+you can do the following trick for several symbols.
+grep do_signal System.map 
+which emits the following among other things
+0001f4e0 T do_signal 
+now you can do
+
+TR I PSWA 0001f4e0 cmd msg * do_signal
+This sends a message to your own console each time do_signal is entered.
+( As an aside I wrote a perl script once which automatically generated a REXX
+script with breakpoints on every kernel procedure, this isn't a good idea
+because there are thousands of these routines & VM can only set 255 breakpoints
+at a time so you nearly had to spend as long pruning the file down as you would 
+entering the msg's by hand ),however, the trick might be useful for a single object file.
+On linux'es 3270 emulator x3270 there is a very useful option under the file ment
+Save Screens In File this is very good of keeping a copy of traces. 
+
+From CMS help <command name> will give you online help on a particular command. 
+e.g. 
+HELP DISPLAY
+
+Also CP has a file called profile.exec which automatically gets called
+on startup of CMS ( like autoexec.bat ), keeping on a DOS analogy session
+CP has a feature similar to doskey, it may be useful for you to
+use profile.exec to define some keystrokes. 
+e.g.
+SET PF9 IMM B
+This does a single step in VM on pressing F8. 
+SET PF10  ^
+This sets up the ^ key.
+which can be used for ^c (ctrl-c),^z (ctrl-z) which can't be typed directly into some 3270 consoles.
+SET PF11 ^-
+This types the starting keystrokes for a sysrq see SysRq below.
+SET PF12 RETRIEVE
+This retrieves command history on pressing F12.
+
+
+Sometimes in VM the display is set up to scroll automatically this
+can be very annoying if there are messages you wish to look at
+to stop this do
+TERM MORE 255 255
+This will nearly stop automatic screen updates, however it will
+cause a denial of service if lots of messages go to the 3270 console,
+so it would be foolish to use this as the default on a production machine.
+ 
+
+Tracing particular processes
+----------------------------
+The kernels text segment is intentionally at an address in memory that it will
+very seldom collide with text segments of user programs ( thanks Martin ),
+this simplifies debugging the kernel.
+However it is quite common for user processes to have addresses which collide
+this can make debugging a particular process under VM painful under normal
+circumstances as the process may change when doing a 
+TR I R <address range>.
+Thankfully after reading VM's online help I figured out how to debug
+I particular process.
+
+Your first problem is to find the STD ( segment table designation )
+of the program you wish to debug.
+There are several ways you can do this here are a few
+1) objdump --syms <program to be debugged> | grep main
+To get the address of main in the program.
+tr i pswa <address of main>
+Start the program, if VM drops to CP on what looks like the entry
+point of the main function this is most likely the process you wish to debug.
+Now do a D X13 or D XG13 on zSeries.
+On 31 bit the STD is bits 1-19 ( the STO segment table origin ) 
+& 25-31 ( the STL segment table length ) of CR13.
+now type
+TR I R STD <CR13's value> 0.7fffffff
+e.g.
+TR I R STD 8F32E1FF 0.7fffffff
+Another very useful variation is
+TR STORE INTO STD <CR13's value> <address range>
+
+
+
+
+Tracing Program Exceptions
+--------------------------
+If you get a crash which says something like
+illegal operation or specification exception followed by a register dump
+You can restart linux & trace these using the tr prog <range or value> trace option.
+
+
+
+The most common ones you will normally be tracing for is
+1=operation exception
+2=privileged operation exception
+4=protection exception
+5=addressing exception
+6=specification exception
+10=segment translation exception
+11=page translation exception
+
+The full list of these is on page 22 of the current s/390 Reference Summary.
+e.g.
+tr prog 10 will trace segment translation exceptions.
+tr prog on its own will trace all program interruption codes.
+
+Trace Sets
+----------
+On starting VM you are initially in the INITIAL trace set.
+You can do a Q TR to verify this.
+If you have a complex tracing situation where you wish to wait for instance 
+till a driver is open before you start tracing IO, but know in your
+heart that you are going to have to make several runs through the code till you
+have a clue whats going on. 
+
+What you can do is
+TR I PSWA <Driver open address>
+hit b to continue till breakpoint
+reach the breakpoint
+now do your
+TR GOTO B 
+TR IO 7c08-7c09 inst int run 
+or whatever the IO channels you wish to trace are & hit b
+
+To got back to the initial trace set do
+TR GOTO INITIAL
+& the TR I PSWA <Driver open address> will be the only active breakpoint again.
+
+
+Tracing linux syscalls under VM
+-------------------------------
+Syscalls are implemented on Linux for S390 by the Supervisor call instruction (SVC) there 256 
+possibilities of these as the instruction is made up of a  0xA opcode & the second byte being
+the syscall number. They are traced using the simple command.
+TR SVC  <Optional value or range>
+the syscalls are defined in linux/include/asm-s390/unistd.h
+e.g. to trace all file opens just do
+TR SVC 5 ( as this is the syscall number of open )
+
+
+SMP Specific commands
+---------------------
+To find out how many cpus you have
+Q CPUS displays all the CPU's available to your virtual machine
+To find the cpu that the current cpu VM debugger commands are being directed at do
+Q CPU to change the current cpu cpu VM debugger commands are being directed at do
+CPU <desired cpu no>
+
+On a SMP guest issue a command to all CPUs try prefixing the command with cpu all.
+To issue a command to a particular cpu try cpu <cpu number> e.g.
+CPU 01 TR I R 2000.3000
+If you are running on a guest with several cpus & you have a IO related problem
+& cannot follow the flow of code but you know it isnt smp related.
+from the bash prompt issue
+shutdown -h now or halt.
+do a Q CPUS to find out how many cpus you have
+detach each one of them from cp except cpu 0 
+by issueing a 
+DETACH CPU 01-(number of cpus in configuration)
+& boot linux again.
+TR SIGP will trace inter processor signal processor instructions.
+DEFINE CPU 01-(number in configuration) 
+will get your guests cpus back.
+
+
+Help for displaying ascii textstrings
+-------------------------------------
+As textstrings are cannot be displayed in ASCII under the VM debugger ( I love EBDIC too ) I have 
+written this little program which will convert a command line of hex digits to ascii text
+which can be compiled under linux & you can copy the hex digits from your x3270 terminal to
+your xterm if you are debugging from a linuxbox.
+
+This is quite useful when looking at a parameter passed in as a text string
+under VM ( unless you are good at decoding ASCII in your head ).
+
+e.g. consider tracing an open syscall
+TR SVC 5
+We have stopped at a breakpoint
+000151B0' SVC   0A05     -> 0001909A'   CC 0
+
+D 20.8 to check the SVC old psw in the prefix area & see was it from userspace
+( for the layout of the prefix area consult P18 of the s/390 390 Reference Summary 
+if you have it available ).
+V00000020  070C2000 800151B2
+The problem state bit wasn't set &  it's also too early in the boot sequence
+for it to be a userspace SVC if it was we would have to temporarily switch the 
+psw to user space addressing so we could get at the first parameter of the open in
+gpr2.
+Next do a 
+D G2
+GPR  2 =  00014CB4
+Now display what gpr2 is pointing to
+D 00014CB4.20
+V00014CB4  2F646576 2F636F6E 736F6C65 00001BF5
+V00014CC4  FC00014C B4001001 E0001000 B8070707
+Now copy the text till the first 00 hex ( which is the end of the string
+to an xterm & do hex2ascii on it.
+hex2ascii 2F646576 2F636F6E 736F6C65 00 
+outputs
+Decoded Hex:=/ d e v / c o n s o l e 0x00 
+We were opening the console device,
+
+You can compile the code below yourself for practice :-),
+/*
+ *    hex2ascii.c
+ *    a useful little tool for converting a hexadecimal command line to ascii
+ *
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *    (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation.
+ */   
+#include <stdio.h>
+
+int main(int argc,char *argv[])
+{
+  int cnt1,cnt2,len,toggle=0;
+  int startcnt=1;
+  unsigned char c,hex;
+  
+  if(argc>1&&(strcmp(argv[1],"-a")==0))
+     startcnt=2;
+  printf("Decoded Hex:=");
+  for(cnt1=startcnt;cnt1<argc;cnt1++)
+  {
+    len=strlen(argv[cnt1]);
+    for(cnt2=0;cnt2<len;cnt2++)
+    {
+       c=argv[cnt1][cnt2];
+       if(c>='0'&&c<='9')
+	  c=c-'0';
+       if(c>='A'&&c<='F')
+	  c=c-'A'+10;
+       if(c>='a'&&c<='F')
+	  c=c-'a'+10;
+       switch(toggle)
+       {
+	  case 0:
+	     hex=c<<4;
+	     toggle=1;
+	  break;
+	  case 1:
+	     hex+=c;
+	     if(hex<32||hex>127)
+	     {
+		if(startcnt==1)
+		   printf("0x%02X ",(int)hex);
+		else
+		   printf(".");
+	     }
+	     else
+	     {
+	       printf("%c",hex);
+	       if(startcnt==1)
+		  printf(" ");
+	     }
+	     toggle=0;
+	  break;
+       }
+    }
+  }
+  printf("\n");
+}
+
+
+
+
+Stack tracing under VM
+----------------------
+A basic backtrace
+-----------------
+
+Here are the tricks I use 9 out of 10 times it works pretty well,
+
+When your backchain reaches a dead end
+--------------------------------------
+This can happen when an exception happens in the kernel & the kernel is entered twice
+if you reach the NULL pointer at the end of the back chain you should be
+able to sniff further back if you follow the following tricks.
+1) A kernel address should be easy to recognise since it is in
+primary space & the problem state bit isn't set & also
+The Hi bit of the address is set.
+2) Another backchain should also be easy to recognise since it is an 
+address pointing to another address approximately 100 bytes or 0x70 hex
+behind the current stackpointer.
+
+
+Here is some practice.
+boot the kernel & hit PA1 at some random time
+d g to display the gprs, this should display something like
+GPR  0 =  00000001  00156018  0014359C  00000000
+GPR  4 =  00000001  001B8888  000003E0  00000000
+GPR  8 =  00100080  00100084  00000000  000FE000
+GPR 12 =  00010400  8001B2DC  8001B36A  000FFED8
+Note that GPR14 is a return address but as we are real men we are going to
+trace the stack.
+display 0x40 bytes after the stack pointer.
+
+V000FFED8  000FFF38 8001B838 80014C8E 000FFF38
+V000FFEE8  00000000 00000000 000003E0 00000000
+V000FFEF8  00100080 00100084 00000000 000FE000
+V000FFF08  00010400 8001B2DC 8001B36A 000FFED8
+
+
+Ah now look at whats in sp+56 (sp+0x38) this is 8001B36A our saved r14 if
+you look above at our stackframe & also agrees with GPR14.
+
+now backchain 
+d 000FFF38.40
+we now are taking the contents of SP to get our first backchain.
+
+V000FFF38  000FFFA0 00000000 00014995 00147094
+V000FFF48  00147090 001470A0 000003E0 00000000
+V000FFF58  00100080 00100084 00000000 001BF1D0
+V000FFF68  00010400 800149BA 80014CA6 000FFF38
+
+This displays a 2nd return address of 80014CA6
+
+now do d 000FFFA0.40 for our 3rd backchain
+
+V000FFFA0  04B52002 0001107F 00000000 00000000
+V000FFFB0  00000000 00000000 FF000000 0001107F
+V000FFFC0  00000000 00000000 00000000 00000000
+V000FFFD0  00010400 80010802 8001085A 000FFFA0
+
+
+our 3rd return address is 8001085A
+
+as the 04B52002 looks suspiciously like rubbish it is fair to assume that the kernel entry routines
+for the sake of optimisation dont set up a backchain.
+
+now look at System.map to see if the addresses make any sense.
+
+grep -i 0001b3 System.map
+outputs among other things
+0001b304 T cpu_idle 
+so 8001B36A
+is cpu_idle+0x66 ( quiet the cpu is asleep, don't wake it )
+
+
+grep -i 00014 System.map 
+produces among other things
+00014a78 T start_kernel  
+so 0014CA6 is start_kernel+some hex number I can't add in my head.
+
+grep -i 00108 System.map 
+this produces
+00010800 T _stext
+so   8001085A is _stext+0x5a
+
+Congrats you've done your first backchain.
+
+
+
+s/390 & zSeries IO Overview
+===========================
+
+I am not going to give a course in 390 IO architecture as this would take me quite a
+while & I'm no expert. Instead I'll give a 390 IO architecture summary for Dummies if you have 
+the s/390 principles of operation available read this instead. If nothing else you may find a few 
+useful keywords in here & be able to use them on a web search engine like altavista to find 
+more useful information.
+
+Unlike other bus architectures modern 390 systems do their IO using mostly
+fibre optics & devices such as tapes & disks can be shared between several mainframes,
+also S390 can support upto 65536 devices while a high end PC based system might be choking 
+with around 64. Here is some of the common IO terminology
+
+Subchannel:
+This is the logical number most IO commands use to talk to an IO device there can be upto
+0x10000 (65536) of these in a configuration typically there is a few hundred. Under VM
+for simplicity they are allocated contiguously, however on the native hardware they are not
+they typically stay consistent between boots provided no new hardware is inserted or removed.
+Under Linux for 390 we use these as IRQ's & also when issuing an IO command (CLEAR SUBCHANNEL,
+HALT SUBCHANNEL,MODIFY SUBCHANNEL,RESUME SUBCHANNEL,START SUBCHANNEL,STORE SUBCHANNEL & 
+TEST SUBCHANNEL ) we use this as the ID of the device we wish to talk to, the most
+important of these instructions are START SUBCHANNEL ( to start IO ), TEST SUBCHANNEL ( to check
+whether the IO completed successfully ), & HALT SUBCHANNEL ( to kill IO ), a subchannel
+can have up to 8 channel paths to a device this offers redunancy if one is not available.
+
+
+Device Number:
+This number remains static & Is closely tied to the hardware, there are 65536 of these
+also they are made up of a CHPID ( Channel Path ID, the most significant 8 bits ) 
+& another lsb 8 bits. These remain static even if more devices are inserted or removed
+from the hardware, there is a 1 to 1 mapping between Subchannels & Device Numbers provided
+devices arent inserted or removed.
+
+Channel Control Words:
+CCWS are linked lists of instructions initially pointed to by an operation request block (ORB),
+which is initially given to Start Subchannel (SSCH) command along with the subchannel number
+for the IO subsystem to process while the CPU continues executing normal code.
+These come in two flavours, Format 0 ( 24 bit for backward )
+compatibility & Format 1 ( 31 bit ). These are typically used to issue read & write 
+( & many other instructions ) they consist of a length field & an absolute address field.
+For each IO typically get 1 or 2 interrupts one for channel end ( primary status ) when the
+channel is idle & the second for device end ( secondary status ) sometimes you get both
+concurrently, you check how the IO went on by issueing a TEST SUBCHANNEL at each interrupt,
+from which you receive an Interruption response block (IRB). If you get channel & device end 
+status in the IRB without channel checks etc. your IO probably went okay. If you didn't you
+probably need a doctorto examine the IRB & extended status word etc.
+If an error occurs more sophistocated control units have a facitity known as
+concurrent sense this means that if an error occurs Extended sense information will
+be presented in the Extended status word in the IRB if not you have to issue a
+subsequent SENSE CCW command after the test subchannel. 
+
+
+TPI( Test pending interrupt) can also be used for polled IO but in multitasking multiprocessor
+systems it isn't recommended except for checking special cases ( i.e. non looping checks for
+pending IO etc. ).
+
+Store Subchannel & Modify Subchannel can be used to examine & modify operating characteristics
+of a subchannel ( e.g. channel paths ).
+
+Other IO related Terms:
+Sysplex: S390's Clustering Technology
+QDIO: S390's new high speed IO architecture to support devices such as gigabit ethernet,
+this architecture is also designed to be forward compatible with up & coming 64 bit machines.
+
+
+General Concepts 
+
+Input Output Processors (IOP's) are responsible for communicating between
+the mainframe CPU's & the channel & relieve the mainframe CPU's from the
+burden of communicating with IO devices directly, this allows the CPU's to 
+concentrate on data processing. 
+
+IOP's can use one or more links ( known as channel paths ) to talk to each 
+IO device. It first checks for path availability & chooses an available one,
+then starts ( & sometimes terminates IO ).
+There are two types of channel path ESCON & the Paralell IO interface.
+
+IO devices are attached to control units, control units provide the
+logic to interface the channel paths & channel path IO protocols to 
+the IO devices, they can be integrated with the devices or housed separately
+& often talk to several similar devices ( typical examples would be raid 
+controllers or a control unit which connects to 1000 3270 terminals ).
+
+
+    +---------------------------------------------------------------+
+    | +-----+ +-----+ +-----+ +-----+  +----------+  +----------+   |
+    | | CPU | | CPU | | CPU | | CPU |  |  Main    |  | Expanded |   |
+    | |     | |     | |     | |     |  |  Memory  |  |  Storage |   |
+    | +-----+ +-----+ +-----+ +-----+  +----------+  +----------+   | 
+    |---------------------------------------------------------------+
+    |   IOP        |      IOP      |       IOP                      |
+    |---------------------------------------------------------------
+    | C | C | C | C | C | C | C | C | C | C | C | C | C | C | C | C | 
+    ----------------------------------------------------------------
+         ||                                              ||
+         ||  Bus & Tag Channel Path                      || ESCON
+         ||  ======================                      || Channel
+         ||  ||                  ||                      || Path
+    +----------+               +----------+         +----------+
+    |          |               |          |         |          |
+    |    CU    |               |    CU    |         |    CU    |
+    |          |               |          |         |          |
+    +----------+               +----------+         +----------+
+       |      |                     |                |       |
++----------+ +----------+      +----------+   +----------+ +----------+
+|I/O Device| |I/O Device|      |I/O Device|   |I/O Device| |I/O Device|
++----------+ +----------+      +----------+   +----------+ +----------+
+  CPU = Central Processing Unit    
+  C = Channel                      
+  IOP = IP Processor               
+  CU = Control Unit
+
+The 390 IO systems come in 2 flavours the current 390 machines support both
+
+The Older 360 & 370 Interface,sometimes called the paralell I/O interface,
+sometimes called Bus-and Tag & sometimes Original Equipment Manufacturers
+Interface (OEMI).
+
+This byte wide paralell channel path/bus has parity & data on the "Bus" cable 
+& control lines on the "Tag" cable. These can operate in byte multiplex mode for
+sharing between several slow devices or burst mode & monopolize the channel for the
+whole burst. Upto 256 devices can be addressed  on one of these cables. These cables are
+about one inch in diameter. The maximum unextended length supported by these cables is
+125 Meters but this can be extended up to 2km with a fibre optic channel extended 
+such as a 3044. The maximum burst speed supported is 4.5 megabytes per second however
+some really old processors support only transfer rates of 3.0, 2.0 & 1.0 MB/sec.
+One of these paths can be daisy chained to up to 8 control units.
+
+
+ESCON if fibre optic it is also called FICON 
+Was introduced by IBM in 1990. Has 2 fibre optic cables & uses either leds or lasers
+for communication at a signaling rate of upto 200 megabits/sec. As 10bits are transferred
+for every 8 bits info this drops to 160 megabits/sec & to 18.6 Megabytes/sec once
+control info & CRC are added. ESCON only operates in burst mode.
+ 
+ESCONs typical max cable length is 3km for the led version & 20km for the laser version
+known as XDF ( extended distance facility ). This can be further extended by using an
+ESCON director which triples the above mentioned ranges. Unlike Bus & Tag as ESCON is
+serial it uses a packet switching architecture the standard Bus & Tag control protocol
+is however present within the packets. Upto 256 devices can be attached to each control 
+unit that uses one of these interfaces.
+
+Common 390 Devices include:
+Network adapters typically OSA2,3172's,2116's & OSA-E gigabit ethernet adapters,
+Consoles 3270 & 3215 ( a teletype emulated under linux for a line mode console ).
+DASD's direct access storage devices ( otherwise known as hard disks ).
+Tape Drives.
+CTC ( Channel to Channel Adapters ),
+ESCON or Paralell Cables used as a very high speed serial link
+between 2 machines. We use 2 cables under linux to do a bi-directional serial link.
+
+
+Debugging IO on s/390 & zSeries under VM
+=========================================
+
+Now we are ready to go on with IO tracing commands under VM
+
+A few self explanatory queries:
+Q OSA
+Q CTC
+Q DISK
+Q DASD
+
+
+
+
+
+
+Q OSA on my machine returns
+OSA  7C08 ON OSA   7C08 SUBCHANNEL = 0000
+OSA  7C09 ON OSA   7C09 SUBCHANNEL = 0001
+OSA  7C14 ON OSA   7C14 SUBCHANNEL = 0002
+OSA  7C15 ON OSA   7C15 SUBCHANNEL = 0003
+
+If you have a guest with certain priviliges you may be able to see devices
+which don't belong to you to avoid this do add the option V.
+e.g.
+Q V OSA
+
+Now using the device numbers returned by this command we will
+Trace the io starting up on the first device 7c08 & 7c09
+In our simplest case we can trace the 
+start subchannels
+like TR SSCH 7C08-7C09
+or the halt subchannels
+or TR HSCH 7C08-7C09
+MSCH's ,STSCH's I think you can guess the rest
+
+Ingo's favourite trick is tracing all the IO's & CCWS & spooling them into the reader of another
+VM guest so he can ftp the logfile back to his own machine.I'll do a small bit of this & give you
+ a look at the output.
+
+1) Spool stdout to VM reader
+SP PRT TO (another vm guest ) or * for the local vm guest
+2) Fill the reader with the trace
+TR IO 7c08-7c09 INST INT CCW PRT RUN
+3) Start up linux 
+i 00c  
+4) Finish the trace
+TR END
+5) close the reader
+C PRT
+6) list reader contents
+RDRLIST
+7) copy it to linux4's minidisk 
+RECEIVE / LOG TXT A1 ( replace
+8)
+filel & press F11 to look at it
+You should see someting like.
+
+00020942' SSCH  B2334000    0048813C    CC 0    SCH 0000    DEV 7C08
+          CPA 000FFDF0   PARM 00E2C9C4    KEY 0  FPI C0  LPM 80
+          CCW    000FFDF0  E4200100 00487FE8   0000  E4240100 ........
+          IDAL                                      43D8AFE8
+          IDAL                                      0FB76000
+00020B0A'   I/O DEV 7C08 -> 000197BC'   SCH 0000   PARM 00E2C9C4
+00021628' TSCH  B2354000 >> 00488164    CC 0    SCH 0000    DEV 7C08
+          CCWA 000FFDF8   DEV STS 0C  SCH STS 00  CNT 00EC
+           KEY 0   FPI C0  CC 0   CTLS 4007
+00022238' STSCH B2344000 >> 00488108    CC 0    SCH 0000    DEV 7C08
+
+If you don't like messing up your readed ( because you possibly booted from it )
+you can alternatively spool it to another readers guest.
+
+
+Other common VM device related commands
+---------------------------------------------
+These commands are listed only because they have
+been of use to me in the past & may be of use to
+you too. For more complete info on each of the commands
+use type HELP <command> from CMS.
+detaching devices
+DET <devno range>
+ATT <devno range> <guest> 
+attach a device to guest * for your own guest
+READY <devno> cause VM to issue a fake interrupt.
+
+The VARY command is normally only available to VM administrators.
+VARY ON PATH <path> TO <devno range>
+VARY OFF PATH <PATH> FROM <devno range>
+This is used to switch on or off channel paths to devices.
+
+Q CHPID <channel path ID>
+This displays state of devices using this channel path
+D SCHIB <subchannel>
+This displays the subchannel information SCHIB block for the device.
+this I believe is also only available to administrators.
+DEFINE CTC <devno>
+defines a virtual CTC channel to channel connection
+2 need to be defined on each guest for the CTC driver to use.
+COUPLE  devno userid remote devno
+Joins a local virtual device to a remote virtual device
+( commonly used for the CTC driver ).
+
+Building a VM ramdisk under CMS which linux can use
+def vfb-<blocksize> <subchannel> <number blocks>
+blocksize is commonly 4096 for linux.
+Formatting it
+format <subchannel> <driver letter e.g. x> (blksize <blocksize>
+
+Sharing a disk between multiple guests
+LINK userid devno1 devno2 mode password
+
+
+
+GDB on S390
+===========
+N.B. if compiling for debugging gdb works better without optimisation 
+( see Compiling programs for debugging )
+
+invocation
+----------
+gdb <victim program> <optional corefile>
+
+Online help
+-----------
+help: gives help on commands
+e.g.
+help
+help display
+Note gdb's online help is very good use it.
+
+
+Assembly
+--------
+info registers: displays registers other than floating point.
+info all-registers: displays floating points as well.
+disassemble: dissassembles
+e.g.
+disassemble without parameters will disassemble the current function
+disassemble $pc $pc+10 
+
+Viewing & modifying variables
+-----------------------------
+print or p: displays variable or register
+e.g. p/x $sp will display the stack pointer
+
+display: prints variable or register each time program stops
+e.g.
+display/x $pc will display the program counter
+display argc
+
+undisplay : undo's display's
+
+info breakpoints: shows all current breakpoints
+
+info stack: shows stack back trace ( if this dosent work too well, I'll show you the
+stacktrace by hand below ).
+
+info locals: displays local variables.
+
+info args: display current procedure arguments.
+
+set args: will set argc & argv each time the victim program is invoked.
+
+set <variable>=value
+set argc=100
+set $pc=0
+
+
+
+Modifying execution
+-------------------
+step: steps n lines of sourcecode
+step steps 1 line.
+step 100 steps 100 lines of code.
+
+next: like step except this will not step into subroutines
+
+stepi: steps a single machine code instruction.
+e.g. stepi 100
+
+nexti: steps a single machine code instruction but will not step into subroutines.
+
+finish: will run until exit of the current routine
+
+run: (re)starts a program
+
+cont: continues a program
+
+quit: exits gdb.
+
+
+breakpoints
+------------
+
+break
+sets a breakpoint
+e.g.
+
+break main
+
+break *$pc
+
+break *0x400618
+
+heres a really useful one for large programs
+rbr
+Set a breakpoint for all functions matching REGEXP
+e.g.
+rbr 390
+will set a breakpoint with all functions with 390 in their name.
+
+info breakpoints
+lists all breakpoints
+
+delete: delete breakpoint by number or delete them all
+e.g.
+delete 1 will delete the first breakpoint
+delete will delete them all
+
+watch: This will set a watchpoint ( usually hardware assisted ),
+This will watch a variable till it changes
+e.g.
+watch cnt, will watch the variable cnt till it changes.
+As an aside unfortunately gdb's, architecture independent watchpoint code
+is inconsistent & not very good, watchpoints usually work but not always.
+
+info watchpoints: Display currently active watchpoints
+
+condition: ( another useful one )
+Specify breakpoint number N to break only if COND is true.
+Usage is `condition N COND', where N is an integer and COND is an
+expression to be evaluated whenever breakpoint N is reached.
+
+
+
+User defined functions/macros
+-----------------------------
+define: ( Note this is very very useful,simple & powerful )
+usage define <name> <list of commands> end
+
+examples which you should consider putting into .gdbinit in your home directory
+define d
+stepi
+disassemble $pc $pc+10
+end
+
+define e
+nexti
+disassemble $pc $pc+10
+end
+
+
+Other hard to classify stuff
+----------------------------
+signal n:
+sends the victim program a signal.
+e.g. signal 3 will send a SIGQUIT.
+
+info signals:
+what gdb does when the victim receives certain signals.
+
+list:
+e.g.
+list lists current function source
+list 1,10 list first 10 lines of curret file.
+list test.c:1,10
+
+
+directory:
+Adds directories to be searched for source if gdb cannot find the source.
+(note it is a bit sensititive about slashes ) 
+e.g. To add the root of the filesystem to the searchpath do
+directory //
+
+
+call <function>
+This calls a function in the victim program, this is pretty powerful
+e.g.
+(gdb) call printf("hello world")
+outputs:
+$1 = 11 
+
+You might now be thinking that the line above didn't work, something extra had to be done.
+(gdb) call fflush(stdout)
+hello world$2 = 0
+As an aside the debugger also calls malloc & free under the hood 
+to make space for the "hello world" string.
+
+
+
+hints
+-----
+1) command completion works just like bash 
+( if you are a bad typist like me this really helps )
+e.g. hit br <TAB> & cursor up & down :-).
+
+2) if you have a debugging problem that takes a few steps to recreate
+put the steps into a file called .gdbinit in your current working directory
+if you have defined a few extra useful user defined commands put these in 
+your home directory & they will be read each time gdb is launched.
+
+A typical .gdbinit file might be.
+break main
+run
+break runtime_exception
+cont 
+
+
+stack chaining in gdb by hand
+-----------------------------
+This is done using a the same trick described for VM 
+p/x (*($sp+56))&0x7fffffff get the first backchain.
+
+For zSeries do
+p/x *($sp+112) i.e. replace 56 with 112 & ignore the &0x7fffffff
+in the macros below.
+
+this outputs 
+$5 = 0x528f18 
+on my machine.
+Now you can use 
+info symbol (*($sp+56))&0x7fffffff 
+you might see something like.
+rl_getc + 36 in section .text  telling you what is located at address 0x528f18
+Now do.
+p/x (*(*$sp+56))&0x7fffffff 
+This outputs
+$6 = 0x528ed0
+Now do.
+info symbol (*(*$sp+56))&0x7fffffff
+rl_read_key + 180 in section .text
+now do
+p/x (*(**$sp+56))&0x7fffffff
+& so on.
+
+Disassembling instructions without debug info
+---------------------------------------------
+gdb typically compains if there is a lack of debugging
+symbols in  the disassemble command with 
+"No function contains specified address." to get around
+this do 
+x/<number lines to disassemble>xi <address>
+e.g.
+x/20xi 0x400730
+
+
+
+Note: Remember gdb has history just like bash you don't need to retype the
+whole line just use the up & down arrows.
+
+
+
+For more info
+-------------
+From your linuxbox do 
+man gdb or info gdb.
+
+core dumps
+----------
+What a core dump ?,
+A core dump is a file generated by the kernel ( if allowed ) which contains the registers,
+& all active pages of the program which has crashed.
+From this file gdb will allow you to look at the registers & stack trace & memory of the
+program as if it just crashed on your system, it is usually called core & created in the
+current working directory.
+This is very useful in that a customer can mail a core dump to a technical support department
+& the technical support department can reconstruct what happened.
+Provided the have an indentical copy of this program with debugging symbols compiled in & 
+the source base of this build is available.
+In short it is far more useful than something like a crash log could ever hope to be.
+
+In theory all that is missing to restart a core dumped program is a kernel patch which
+will do the following.
+1) Make a new kernel task structure
+2) Reload all the dumped pages back into the kernels memory managment structures.
+3) Do the required clock fixups
+4) Get all files & network connections for the process back into an identical state ( really difficult ).
+5) A few more difficult things I haven't thought of.
+
+
+
+Why have I never seen one ?.
+Probably because you haven't used the command 
+ulimit -c unlimited in bash
+to allow core dumps, now do 
+ulimit -a 
+to verify that the limit was accepted.
+
+A sample core dump
+To create this I'm going to do
+ulimit -c unlimited
+gdb 
+to launch gdb (my victim app. ) now be bad & do the following from another 
+telnet/xterm session to the same machine
+ps -aux | grep gdb
+kill -SIGSEGV <gdb's pid>
+or alternatively use killall -SIGSEGV gdb if you have the killall command.
+Now look at the core dump.
+./gdb ./gdb core
+Displays the following
+GNU gdb 4.18
+Copyright 1998 Free Software Foundation, Inc.
+GDB is free software, covered by the GNU General Public License, and you are
+welcome to change it and/or distribute copies of it under certain conditions.
+Type "show copying" to see the conditions.
+There is absolutely no warranty for GDB.  Type "show warranty" for details.
+This GDB was configured as "s390-ibm-linux"...
+Core was generated by `./gdb'.
+Program terminated with signal 11, Segmentation fault.
+Reading symbols from /usr/lib/libncurses.so.4...done.
+Reading symbols from /lib/libm.so.6...done.
+Reading symbols from /lib/libc.so.6...done.
+Reading symbols from /lib/ld-linux.so.2...done.
+#0  0x40126d1a in read () from /lib/libc.so.6
+Setting up the environment for debugging gdb.
+Breakpoint 1 at 0x4dc6f8: file utils.c, line 471.
+Breakpoint 2 at 0x4d87a4: file top.c, line 2609.
+(top-gdb) info stack
+#0  0x40126d1a in read () from /lib/libc.so.6
+#1  0x528f26 in rl_getc (stream=0x7ffffde8) at input.c:402
+#2  0x528ed0 in rl_read_key () at input.c:381
+#3  0x5167e6 in readline_internal_char () at readline.c:454
+#4  0x5168ee in readline_internal_charloop () at readline.c:507
+#5  0x51692c in readline_internal () at readline.c:521
+#6  0x5164fe in readline (prompt=0x7ffff810 "\177˙řx\177˙÷Ř\177˙řxŔ")
+    at readline.c:349
+#7  0x4d7a8a in command_line_input (prrompt=0x564420 "(gdb) ", repeat=1,
+    annotation_suffix=0x4d6b44 "prompt") at top.c:2091
+#8  0x4d6cf0 in command_loop () at top.c:1345
+#9  0x4e25bc in main (argc=1, argv=0x7ffffdf4) at main.c:635
+
+
+LDD
+===
+This is a program which lists the shared libraries which a library needs,
+Note you also get the relocations of the shared library text segments which
+help when using objdump --source.
+e.g.
+ ldd ./gdb
+outputs
+libncurses.so.4 => /usr/lib/libncurses.so.4 (0x40018000)
+libm.so.6 => /lib/libm.so.6 (0x4005e000)
+libc.so.6 => /lib/libc.so.6 (0x40084000)
+/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
+
+
+Debugging shared libraries
+==========================
+Most programs use shared libraries, however it can be very painful
+when you single step instruction into a function like printf for the 
+first time & you end up in functions like _dl_runtime_resolve this is
+the ld.so doing lazy binding, lazy binding is a concept in ELF where 
+shared library functions are not loaded into memory unless they are 
+actually used, great for saving memory but a pain to debug.
+To get around this either relink the program -static or exit gdb type 
+export LD_BIND_NOW=true this will stop lazy binding & restart the gdb'ing 
+the program in question.
+ 
+
+
+Debugging modules
+=================
+As modules are dynamically loaded into the kernel their address can be
+anywhere to get around this use the -m option with insmod to emit a load
+map which can be piped into a file if required.
+
+The proc file system
+====================
+What is it ?.
+It is a filesystem created by the kernel with files which are created on demand
+by the kernel if read, or can be used to modify kernel parameters,
+it is a powerful concept.
+
+e.g.
+
+cat /proc/sys/net/ipv4/ip_forward 
+On my machine outputs 
+0 
+telling me ip_forwarding is not on to switch it on I can do
+echo 1 >  /proc/sys/net/ipv4/ip_forward
+cat it again
+cat /proc/sys/net/ipv4/ip_forward 
+On my machine now outputs
+1
+IP forwarding is on.
+There is a lot of useful info in here best found by going in & having a look around,
+so I'll take you through some entries I consider important.
+
+All the processes running on the machine have there own entry defined by
+/proc/<pid>
+So lets have a look at the init process
+cd /proc/1
+
+cat cmdline
+emits
+init [2]
+
+cd /proc/1/fd
+This contains numerical entries of all the open files,
+some of these you can cat e.g. stdout (2)
+
+cat /proc/29/maps
+on my machine emits
+
+00400000-00478000 r-xp 00000000 5f:00 4103       /bin/bash
+00478000-0047e000 rw-p 00077000 5f:00 4103       /bin/bash
+0047e000-00492000 rwxp 00000000 00:00 0
+40000000-40015000 r-xp 00000000 5f:00 14382      /lib/ld-2.1.2.so
+40015000-40016000 rw-p 00014000 5f:00 14382      /lib/ld-2.1.2.so
+40016000-40017000 rwxp 00000000 00:00 0
+40017000-40018000 rw-p 00000000 00:00 0
+40018000-4001b000 r-xp 00000000 5f:00 14435      /lib/libtermcap.so.2.0.8
+4001b000-4001c000 rw-p 00002000 5f:00 14435      /lib/libtermcap.so.2.0.8
+4001c000-4010d000 r-xp 00000000 5f:00 14387      /lib/libc-2.1.2.so
+4010d000-40111000 rw-p 000f0000 5f:00 14387      /lib/libc-2.1.2.so
+40111000-40114000 rw-p 00000000 00:00 0
+40114000-4011e000 r-xp 00000000 5f:00 14408      /lib/libnss_files-2.1.2.so
+4011e000-4011f000 rw-p 00009000 5f:00 14408      /lib/libnss_files-2.1.2.so
+7fffd000-80000000 rwxp ffffe000 00:00 0
+
+
+Showing us the shared libraries init uses where they are in memory
+& memory access permissions for each virtual memory area.
+
+/proc/1/cwd is a softlink to the current working directory.
+/proc/1/root is the root of the filesystem for this process. 
+
+/proc/1/mem is the current running processes memory which you
+can read & write to like a file.
+strace uses this sometimes as it is a bit faster than the
+rather inefficent ptrace interface for peeking at DATA.
+
+
+cat status 
+
+Name:   init
+State:  S (sleeping)
+Pid:    1
+PPid:   0
+Uid:    0       0       0       0
+Gid:    0       0       0       0
+Groups:
+VmSize:      408 kB
+VmLck:         0 kB
+VmRSS:       208 kB
+VmData:       24 kB
+VmStk:         8 kB
+VmExe:       368 kB
+VmLib:         0 kB
+SigPnd: 0000000000000000
+SigBlk: 0000000000000000
+SigIgn: 7fffffffd7f0d8fc
+SigCgt: 00000000280b2603
+CapInh: 00000000fffffeff
+CapPrm: 00000000ffffffff
+CapEff: 00000000fffffeff
+
+User PSW:    070de000 80414146
+task: 004b6000 tss: 004b62d8 ksp: 004b7ca8 pt_regs: 004b7f68
+User GPRS:
+00000400  00000000  0000000b  7ffffa90
+00000000  00000000  00000000  0045d9f4
+0045cafc  7ffffa90  7fffff18  0045cb08
+00010400  804039e8  80403af8  7ffff8b0
+User ACRS:
+00000000  00000000  00000000  00000000
+00000001  00000000  00000000  00000000
+00000000  00000000  00000000  00000000
+00000000  00000000  00000000  00000000
+Kernel BackChain  CallChain    BackChain  CallChain
+       004b7ca8   8002bd0c     004b7d18   8002b92c
+       004b7db8   8005cd50     004b7e38   8005d12a
+       004b7f08   80019114                     
+Showing among other things memory usage & status of some signals &
+the processes'es registers from the kernel task_structure
+as well as a backchain which may be useful if a process crashes
+in the kernel for some unknown reason.
+
+Some driver debugging techniques
+================================
+high level debugging network drivers
+------------------------------------
+ifconfig is a quite useful command
+it gives the current state of network drivers.
+
+If you suspect your network device driver is dead
+one way to check is type 
+ifconfig <network device> 
+e.g. tr0
+You should see something like
+tr0       Link encap:16/4 Mbps Token Ring (New)  HWaddr 00:04:AC:20:8E:48
+          inet addr:9.164.185.132  Bcast:9.164.191.255  Mask:255.255.224.0
+          UP BROADCAST RUNNING MULTICAST  MTU:2000  Metric:1
+          RX packets:246134 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
+          collisions:0 txqueuelen:100
+
+if the device doesn't say up
+try
+/etc/rc.d/init.d/network start 
+( this starts the network stack & hopefully calls ifconfig tr0 up ).
+ifconfig looks at the output of /proc/net/dev & presents it in a more presentable form
+Now ping the device from a machine in the same subnet.
+if the RX packets count & TX packets counts don't increment you probably
+have problems.
+next 
+cat /proc/net/arp
+Do you see any hardware addresses in the cache if not you may have problems.
+Next try
+ping -c 5 <broadcast_addr> i.e. the Bcast field above in the output of
+ifconfig. Do you see any replies from machines other than the local machine
+if not you may have problems. also if the TX packets count in ifconfig
+hasn't incremented either you have serious problems in your driver 
+(e.g. the txbusy field of the network device being stuck on ) 
+or you may have multiple network devices connected.
+
+
+chandev
+-------
+There is a new device layer for channel devices, some
+drivers e.g. lcs are registered with this layer.
+If the device uses the channel device layer you'll be
+able to find what interupts it uses & the current state 
+of the device.
+See the manpage chandev.8 &type cat /proc/chandev for more info.
+
+
+
+Starting points for debugging scripting languages etc.
+======================================================
+
+bash/sh
+
+bash -x <scriptname>
+e.g. bash -x /usr/bin/bashbug
+displays the following lines as it executes them.
++ MACHINE=i586
++ OS=linux-gnu
++ CC=gcc
++ CFLAGS= -DPROGRAM='bash' -DHOSTTYPE='i586' -DOSTYPE='linux-gnu' -DMACHTYPE='i586-pc-linux-gnu' -DSHELL -DHAVE_CONFIG_H   -I. -I. -I./lib -O2 -pipe
++ RELEASE=2.01
++ PATCHLEVEL=1
++ RELSTATUS=release
++ MACHTYPE=i586-pc-linux-gnu   
+
+perl -d <scriptname> runs the perlscript in a fully intercative debugger
+<like gdb>.
+Type 'h' in the debugger for help.
+
+for debugging java type
+jdb <filename> another fully interactive gdb style debugger.
+& type ? in the debugger for help.
+
+
+Debugging Drivers
+=================
+Some of our drivers now support a debug logging feature in
+/proc/s390dbf see s390dbf.txt in the linux/Documentation directory
+for more info.
+e.g. 
+to switch on lcs debugging
+echo 5 > /proc/s390dbf/lcs/level
+& then after the error occured.
+cat /proc/s390dbf/lcs/sprintf >/logfile
+the logfile now contains some information which may help
+tech support resolve a problem in the field.
+
+If you have VM look at the chapter Debugging IO on S390 under VM.
+
+
+
+
+Tools soon to be available
+==========================
+
+Dumptool & Lcrash
+-----------------
+Michael Holzheu & others here at IBM have a fairly mature port of 
+SGI's lcrash tool which allows one to look at kernel structures in a
+running kernel.
+
+It also complements a tool called dumptool which dumps all the kernels
+memory pages & registers to either a tape or a disk.
+This can be used by tech support or an ambitous end user do
+post mortem debugging of a machine like gdb core dumps.
+
+Going into how to use this tool in detail will be explained
+in other documentation supplied by IBM & the lcrash homepage
+http://oss.sgi.com/projects/lkcd/.
+
+How they work
+-------------
+Lcrash is a perfectly normal application
+however it requires an additional file.
+It is built using a patch to the kernel source base.
+
+
+Debugging a live system it uses /dev/mem
+alternatively for post mortem debugging it uses the data 
+collected by dumptool.
+
+
+Ltrace
+------
+We also have a tool called ltrace in our CVS repository 
+no plans on a delivery date yet.
+ltrace is a superset of strace in that it also allows
+tracing of shared libraries calls as well as system calls,
+man ltrace for more info.
+
+SysRq
+=====
+This is now supported by linux for s/390 & zSeries.
+To enable it do compile the kernel with 
+Kernel Hacking -> Magic SysRq Key Enabled
+echo "1" > /proc/sys/kernel/sysrq.
+On 390 all commands are prefixed with
+^-
+e.g.
+^-t will show tasks.
+^-? or some unknown command will display help.
+The sysrq key reading is very picky ( I have to type the keys in an
+ xterm session & paste them  into the x3270 console )
+& it may be wise to predefine the keys as described in the VM hints above
+
+This is particularly useful for syncing disks unmounting & rebooting
+if the machine gets partially hung.
+
+Read Documentation/sysrq.txt for more info
+
+References:
+===========
+Enterprise Systems Architecture Reference Summary
+Enterprise Systems Architecture Principles of Operation
+Hartmut Penners s390 stack frame sheet.
+IBM Mainframe Channel Attachment a technology brief from a CISCO webpage
+Various bits of man & info pages of Linux.
+Linux & GDB source.
+Various info & man pages.
+CMS Help on tracing commands.
+Linux for s/390 Elf Application Binary Interface
+Linux for zSeries Elf Application Binary Interface ( Both Highly Recommended )
+z/Architecture Principles of Operation SA22-7832-00
+Enterprise Systems Architecture/390 Reference Summary SA22-7209-01 & the
+Enterprise Systems Architecture/390 Principles of Operation SA22-7201-05
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.3/linux/Documentation/s390/chandev.8 linux/Documentation/s390/chandev.8
--- v2.4.3/linux/Documentation/s390/chandev.8	Fri Feb 16 15:53:08 2001
+++ linux/Documentation/s390/chandev.8	Wed Apr 11 19:02:27 2001
@@ -42,8 +42,16 @@
 .It
 Or from the boot command line using the 'chandev=' keyword
 .El
+.Bl -item
+.It
 Multiple options can be passed separated by semicolons but no spaces are allowed between parameters. The script /bin/chandev will be called automatically on startup or a machine check of a device as follows.
 /bin/chandev <start starting_devnames> <machine_check (devnames pre_recovery_action_status) (post_recovery_action_status)>.
+The chandev layer doesn't open stdin stdout or stderr so it is advisable that you add the following lines to the start of your script.
+.It
+#!/bin/bash
+.It
+exec >/dev/console 2>&1 0>&1
+.El
 
 e.g. if tr0 & ctc0 were starting up & eth0 & eth1 didn't recover from a gone machine check at the same instant the  parameters would be.
 
diff -u --recursive --new-file v2.4.3/linux/Documentation/s390/config3270.sh linux/Documentation/s390/config3270.sh
--- v2.4.3/linux/Documentation/s390/config3270.sh	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/s390/config3270.sh	Wed Apr 11 19:02:27 2001
@@ -0,0 +1,66 @@
+#!/bin/sh
+#
+# config3270 -- Autoconfigure /dev/3270/* and /etc/inittab
+#
+#       Usage:
+#               config3270
+#
+#       Output:
+#               /tmp/mkdev3270
+#
+#       Operation:
+#               1. Run this script
+#               2. Run the script it produces: /tmp/mkdev3270
+#               3. Issue "telinit q" or reboot, as appropriate.
+#
+P=/proc/tty/driver/tty3270
+ROOT=
+D=$ROOT/dev
+SUBD=3270
+TTY=$SUBD/tty
+TUB=$SUBD/tub
+SCR=$ROOT/tmp/mkdev3270
+SCRTMP=$SCR.a
+GETTYLINE=:2345:respawn:/sbin/mingetty
+INITTAB=$ROOT/etc/inittab
+NINITTAB=$ROOT/etc/NEWinittab
+OINITTAB=$ROOT/etc/OLDinittab
+ADDNOTE=\\"# Additional mingettys for the 3270/tty* driver, tub3270 ---\\"
+
+if ! ls $P > /dev/null 2>&1; then
+	modprobe tub3270 > /dev/null 2>&1
+fi
+ls $P > /dev/null 2>&1 || exit 1
+
+# Initialize two files, one for /dev/3270 commands and one
+# to replace the /etc/inittab file (old one saved in OLDinittab)
+echo "#!/bin/sh" > $SCR || exit 1
+echo " " >> $SCR
+echo "# Script built by /sbin/config3270" >> $SCR
+echo rm -rf "$D/$SUBD/*" >> $SCR
+echo "grep -v $TTY $INITTAB > $NINITTAB" > $SCRTMP || exit 1
+echo "echo $ADDNOTE >> $NINITTAB" >> $SCRTMP
+echo mkdir -p $D/$SUBD >> $SCR
+
+# Now query the tub3270 driver for 3270 device information
+# and add appropriate mknod and mingetty lines to our files
+echo what=config > $P
+while read devno maj min;do
+	if [ $min = 0 ]; then
+		fsmaj=$maj
+		echo mknod $D/$TUB c $fsmaj 0 >> $SCR
+		echo chmod 666 $D/$TUB >> $SCR
+	elif [ $maj = CONSOLE ]; then
+		echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR
+	else
+		echo mknod $D/$TTY$devno c $maj $min >>$SCR
+		echo mknod $D/$TUB$devno c $fsmaj $min >> $SCR
+		echo "echo t$min$GETTYLINE $TTY$devno >> $NINITTAB" >> $SCRTMP
+	fi
+done < $P
+
+echo mv $INITTAB $OINITTAB >> $SCRTMP || exit 1
+echo mv $NINITTAB $INITTAB >> $SCRTMP
+cat $SCRTMP >> $SCR
+rm $SCRTMP
+exit 0
diff -u --recursive --new-file v2.4.3/linux/Documentation/s390/s390dbf.txt linux/Documentation/s390/s390dbf.txt
--- v2.4.3/linux/Documentation/s390/s390dbf.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/s390/s390dbf.txt	Wed Apr 11 19:02:27 2001
@@ -0,0 +1,558 @@
+S390 Debug Feature
+==================
+
+files: arch/s390/kernel/debug.c
+       include/asm-s390/debug.h
+
+Description:
+------------
+The goal of this feature is to provide a kernel debug logging API 
+where log records can be stored efficiently in memory, where each component 
+(e.g. device drivers) can have one seperate debug log.
+One purpose of this is to inspect the debug logs after a production system crash
+in order to analyze the reason for the crash.
+If the system still runs but only a subcomponent which uses dbf failes,
+it is possible to look at the debug logs on a live system via the Linux proc
+filesystem.
+The debug feature may also very usefull for kernel and driver development.
+
+Design:
+-------
+Kernel components (e.g. device drivers) can register themselves at the debug 
+feature with the function call debug_register(). This function initializes a 
+debug log for the caller. For each debug log exists a number of debug areas 
+where exactly one is active at one time.  Each debug area consists of contiguous
+pages in memory. In the debug areas there are stored debug entries (log records)
+which are written by event- and exception-calls. 
+
+An event-call writes the specified debug entry to the active debug
+area and updates the log pointer for the active area. If the end 
+of the active debug area is reached, a wrap around is done (ring buffer) 
+and the next debug entry will be written at the beginning of the active 
+debug area.
+
+An exception-call writes the specified debug entry to the log and
+switches to the next debug area. This is done in order to be sure
+that the records which describe the origin of the exception are not
+overwritten when a wrap around for the current area occurs.
+
+The debug areas itselve are also ordered in form of a ring buffer. 
+When an exception is thrown in the last debug area, the following debug 
+entries are then written again in the very first area.
+
+There are three versions for the event- and exception-calls: One for
+logging raw data, one for text and one for numbers.
+
+Each debug entry contains the following data:
+
+- Timestamp
+- Cpu-Number of calling task
+- Level of debug entry (0...6)
+- Return Address to caller
+- Flag, if entry is an exception or not
+
+The debug logs can be inspected in a live system through entries in
+the proc-filesystem. Under the path /proc/s390dbf there is 
+a directory for each registered component, which is named like the
+corresponding component.
+
+The content of the directories are files which represent different views
+to the debug log. Each component can decide which views should be
+used through registering them with the function debug_register_view().
+Predefined views for hex/ascii, sprintf and raw binary data are provided.
+It is also possible to define other views. The content of
+a view can be inspected simply by reading the corresponding proc file.
+
+All debug logs have an an actual debug level (range from 0 to 6).
+The default level is 3. Event and Exception functions have a 'level'
+parameter. Only debug entries with a level that is lower or equal
+than the actual level are written to the log. This means that high 
+priority log entries should have a low level value whereas low priority
+entries should have a high one. 
+The actual debug level can be changed with the help of the proc-filesystem 
+through writing a number string "x" to the 'level' proc file which is
+provided for every debug log. Debugging can be switched off completely
+by using "-" on the 'level' proc file.
+
+Example:
+
+> echo "-" > /proc/s390dbf/dasd/level
+
+Kernel Interfaces:
+------------------
+
+----------------------------------------------------------------------------
+debug_info_t *debug_register(char *name, int pages_index, int nr_areas,
+                             int buf_size);
+
+Parameter:    name:        Name of debug log (e.g. used for proc entry) 
+              pages_index: 2^pages_index pages will be allocated per area
+              nr_areas:    number of debug areas
+              buf_size:    size of data area in each debug entry
+
+Return Value: Handle for generated debug area   
+              NULL if register failed 
+
+Description:  Allocates memory for a debug log     
+              Must not be called within an interrupt handler 
+
+---------------------------------------------------------------------------
+void debug_unregister (debug_info_t * id);
+
+Parameter:     id:   handle for debug log  
+
+Return Value:  none 
+
+Description:   frees memory for a debug log     
+               Must not be called within an interrupt handler 
+
+---------------------------------------------------------------------------
+void debug_set_level (debug_info_t * id, int new_level);
+
+Parameter:     id:        handle for debug log  
+               new_level: new debug level 
+
+Return Value:  none 
+
+Description:   Sets new actual debug level if new_level is valid. 
+---------------------------------------------------------------------------
+debug_entry_t* debug_event (debug_info_t* id, int level, void* data, 
+                            int length);
+
+Parameter:     id:     handle for debug log  
+               level:  debug level           
+               data:   pointer to data for debug entry  
+               length: length of data in bytes       
+
+Return Value:  Address of written debug entry 
+
+Description:   writes debug entry to active debug area (if level <= actual 
+               debug level)    
+
+---------------------------------------------------------------------------
+debug_entry_t* debug_int_event (debug_info_t * id, int level, 
+                                unsigned int data);
+debug_entry_t* debug_long_event(debug_info_t * id, int level,
+                                unsigned long data);
+
+Parameter:     id:     handle for debug log  
+               level:  debug level           
+               data:   integer value for debug entry           
+
+Return Value:  Address of written debug entry 
+
+Description:   writes debug entry to active debug area (if level <= actual 
+               debug level)    
+
+---------------------------------------------------------------------------
+debug_entry_t* debug_text_event (debug_info_t * id, int level, 
+                                 const char* data);
+
+Parameter:     id:     handle for debug log  
+               level:  debug level           
+               data:   string for debug entry  
+
+Return Value:  Address of written debug entry 
+
+Description:   writes debug entry in ascii format to active debug area 
+               (if level <= actual debug level)     
+
+---------------------------------------------------------------------------
+debug_entry_t* debug_sprintf_event (debug_info_t * id, int level, 
+                                    char* string,...);
+
+Parameter:     id:    handle for debug log 
+               level: debug level
+               string: format string for debug entry 
+               ...: varargs used as in sprintf()
+
+Return Value:  Address of written debug entry
+
+Description:   writes debug entry with format string and varargs (longs) to 
+               active debug area (if level $<=$ actual debug level). 
+               floats and long long datatypes cannot be used as varargs.
+
+---------------------------------------------------------------------------
+
+debug_entry_t* debug_exception (debug_info_t* id, int level, void* data, 
+                                int length);
+
+Parameter:     id:     handle for debug log  
+               level:  debug level           
+               data:   pointer to data for debug entry  
+               length: length of data in bytes       
+
+Return Value:  Address of written debug entry 
+
+Description:   writes debug entry to active debug area (if level <= actual 
+               debug level) and switches to next debug area  
+
+---------------------------------------------------------------------------
+debug_entry_t* debug_int_exception (debug_info_t * id, int level, 
+                                    unsigned int data);
+debug_entry_t* debug_long_exception(debug_info_t * id, int level,
+                                    unsigned long data);
+
+Parameter:     id:     handle for debug log  
+               level:  debug level           
+               data:   integer value for debug entry           
+
+Return Value:  Address of written debug entry 
+
+Description:   writes debug entry to active debug area (if level <= actual 
+               debug level) and switches to next debug area  
+
+---------------------------------------------------------------------------
+debug_entry_t* debug_text_exception (debug_info_t * id, int level, 
+                                     const char* data);
+
+Parameter:     id:     handle for debug log  
+               level:  debug level           
+               data:   string for debug entry  
+
+Return Value:  Address of written debug entry 
+
+Description:   writes debug entry in ascii format to active debug area 
+               (if level <= actual debug level) and switches to next debug 
+               area  
+
+---------------------------------------------------------------------------
+debug_entry_t* debug_sprintf_exception (debug_info_t * id, int level,
+                                        char* string,...);
+
+Parameter:     id:    handle for debug log  
+               level: debug level  
+               string: format string for debug entry  
+               ...: varargs used as in sprintf()
+
+Return Value:  Address of written debug entry 
+
+Description:   writes debug entry with format string and varargs (longs) to 
+               active debug area (if level $<=$ actual debug level) and
+               switches to next debug area. 
+               floats and long long datatypes cannot be used as varargs.
+
+---------------------------------------------------------------------------
+
+int debug_register_view (debug_info_t * id, struct debug_view *view);
+
+Parameter:     id:    handle for debug log  
+               view:  pointer to debug view struct 
+
+Return Value:  0  : ok 
+               < 0: Error 
+
+Description:   registers new debug view and creates proc dir entry 
+
+---------------------------------------------------------------------------
+int debug_unregister_view (debug_info_t * id, struct debug_view *view); 
+
+Parameter:     id:    handle for debug log  
+               view:  pointer to debug view struct 
+
+Return Value:  0  : ok 
+               < 0: Error 
+
+Description:   unregisters debug view and removes proc dir entry 
+
+
+
+Predefined views:
+-----------------
+
+extern struct debug_view debug_hex_ascii_view;
+extern struct debug_view debug_raw_view;
+extern struct debug_view debug_sprintf_view;
+
+Examples
+--------
+
+/*
+ * hex_ascii- + raw-view Example
+ */
+
+#include <linux/module.h>
+#include <asm/debug.h>
+
+static debug_info_t* debug_info;
+
+int init_module(void)
+{
+    /* register 4 debug areas with one page each and 4 byte data field */
+
+    debug_info = debug_register ("test", 0, 4, 4 );
+    debug_register_view(debug_info,&debug_hex_ascii_view);
+    debug_register_view(debug_info,&debug_raw_view);
+
+    debug_text_event(debug_info, 4 , "one ");
+    debug_int_exception(debug_info, 4, 4711);
+    debug_event(debug_info, 3, &debug_info, 4);
+
+    return 0;
+}
+
+void cleanup_module(void)
+{
+    debug_unregister (debug_info);
+}
+
+---------------------------------------------------------------------------
+
+/*
+ * sprintf-view Example
+ */
+
+#include <linux/module.h>
+#include <asm/debug.h>
+
+static debug_info_t* debug_info;
+
+int init_module(void)
+{
+    /* register 4 debug areas with one page each and data field for */
+    /* format string pointer + 2 varargs (= 3 * sizeof(long))       */
+
+    debug_info = debug_register ("test", 0, 4, sizeof(long) * 3);
+    debug_register_view(debug_info,&debug_sprintf_view);
+
+    debug_sprintf_event(debug_info, 2 , "first event in %s:%i\n",__FILE__,__LINE__);
+    debug_sprintf_exception(debug_info, 1, "pointer to debug info: %p\n",&debug_info);
+
+    return 0;
+}
+
+void cleanup_module(void)
+{
+    debug_unregister (debug_info);
+}
+
+
+
+ProcFS Interface
+----------------
+Views to the debug logs can be investigated through reading the corresponding 
+proc-files:
+
+Example:
+
+> ls /proc/s390dbf/dasd
+hex_ascii  level      raw
+> cat /proc/s390dbf/dasd/hex_ascii | sort +1
+00 00974733272:680099 2 - 02 0006ad7e  07 ea 4a 90 | ....
+00 00974733272:682210 2 - 02 0006ade6  46 52 45 45 | FREE
+00 00974733272:682213 2 - 02 0006adf6  07 ea 4a 90 | ....
+00 00974733272:682281 1 * 02 0006ab08  41 4c 4c 43 | EXCP 
+01 00974733272:682284 2 - 02 0006ab16  45 43 4b 44 | ECKD
+01 00974733272:682287 2 - 02 0006ab28  00 00 00 04 | ....
+01 00974733272:682289 2 - 02 0006ab3e  00 00 00 20 | ... 
+01 00974733272:682297 2 - 02 0006ad7e  07 ea 4a 90 | ....
+01 00974733272:684384 2 - 00 0006ade6  46 52 45 45 | FREE
+01 00974733272:684388 2 - 00 0006adf6  07 ea 4a 90 | ....
+
+See section about predefined views for explanation of the above output!
+
+Changing the debug level
+------------------------
+
+Example:
+
+
+> cat /proc/s390dbf/dasd/level
+3
+> echo "5" > /proc/s390dbf/dasd/level
+> cat /proc/s390dbf/dasd/level
+5
+
+lcrash Interface
+----------------
+It is planned that the dump analysis tool lcrash gets an additional command
+'s390dbf' to display all the debug logs. With this tool it will be possible 
+to investigate the debug logs on a live system and with a memory dump after 
+a system crash.
+
+Investigating raw memory
+------------------------
+One last possibility to investigate the debug logs at a live
+system and after a system crash is to look at the raw memory
+under VM or at the Service Element.
+It is possible to find the anker of the debug-logs through
+the 'debug_area_first' symbol in the System map. Then one has
+to follow the correct pointers of the data-structures defined
+in debug.h and find the debug-areas in memory.
+Normally modules which use the debug feature will also have
+a global variable with the pointer to the debug-logs. Following
+this pointer it will also be possible to find the debug logs in
+memory.
+
+For this method it is recommended to use '16 * x + 4' byte (x = 0..n)
+for the length of the data field in debug_register() in
+order to see the debug entries well formatted.
+
+
+Predefined Views
+----------------
+
+There are three predefined views: hex_ascii, raw and sprintf. 
+The hex_ascii view shows the data field in hex and ascii representation 
+(e.g. '45 43 4b 44 | ECKD'). 
+The raw view returns a bytestream as the debug areas are stored in memory.
+
+The sprintf view formats the debug entries in the same way as the sprintf
+function would do. The sprintf event/expection fuctions write to the 
+debug entry a pointer to the format string (size = sizeof(long)) 
+and for each vararg a long value. So e.g. for a debug entry with a format 
+string plus two varargs one would need to allocate a (3 * sizeof(long)) 
+byte data area in the debug_register() function.
+
+
+NOTE: If using the sprintf view do NOT use other event/exception functions
+than the sprintf-event and -exception functions.
+
+The format of the hex_ascii and sprintf view is as follows:
+- Number of area
+- Timestamp (formatted as seconds and microseconds since 00:00:00 Coordinated 
+  Universal Time (UTC), January 1, 1970)
+- level of debug entry
+- Exception flag (* = Exception)
+- Cpu-Number of calling task
+- Return Address to caller
+- data field
+
+The format of the raw view is:
+- Header as described in debug.h
+- datafield 
+
+A typical line of the hex_ascii view will look like the following (first line 
+is only for explanation and will not be displayed when 'cating' the view):
+
+area  time           level exception cpu caller    data (hex + ascii)
+--------------------------------------------------------------------------
+00    00964419409:440690 1 -         00  88023fe   
+
+
+Defining views
+--------------
+
+Views are specified with the 'debug_view' structure. There are defined
+callback functions which are used for reading and writing the proc files:
+
+struct debug_view {
+        char name[DEBUG_MAX_PROCF_LEN];  
+        debug_prolog_proc_t* prolog_proc; 
+        debug_header_proc_t* header_proc;
+        debug_format_proc_t* format_proc;
+        debug_input_proc_t*  input_proc;
+	void*                private_data;
+};
+
+where
+
+typedef int (debug_header_proc_t) (debug_info_t* id,
+                                   struct debug_view* view,
+                                   int area,
+                                   debug_entry_t* entry,
+                                   char* out_buf);
+
+typedef int (debug_format_proc_t) (debug_info_t* id,
+                                   struct debug_view* view, char* out_buf,
+                                   const char* in_buf);
+typedef int (debug_prolog_proc_t) (debug_info_t* id,
+                                   struct debug_view* view,
+                                   char* out_buf);
+typedef int (debug_input_proc_t) (debug_info_t* id,
+                                  struct debug_view* view,
+                                  struct file* file, const char* user_buf,
+                                  size_t in_buf_size, loff_t* offset);
+
+
+The "private_data" member can be used as pointer to view specific data.
+It is not used by the debug feature itself.
+
+The output when reading a debug-proc file is structured like this:
+
+"prolog_proc output"
+
+"header_proc output 1"  "format_proc output 1"
+"header_proc output 2"  "format_proc output 2"
+"header_proc output 3"  "format_proc output 3"
+...
+
+When a view is read from the proc fs, the Debug Feature calls the 
+'prolog_proc' once for writing the prolog.
+Then 'header_proc' and 'format_proc' are called for each 
+existing debug entry.
+
+The input_proc can be used to implement functionality when it is written to 
+the view (e.g. like with 'echo "0" > /proc/s390dbf/dasd/level).
+
+For header_proc there can be used the default function
+debug_dflt_header_fn() which is defined in in debug.h.
+and which produces the same header output as the predefined views.
+E.g:
+00 00964419409:440761 2 - 00 88023ec
+
+In order to see how to use the callback functions check the implementation
+of the default views!
+
+Example
+
+#include <asm/debug.h>
+
+#define UNKNOWNSTR "data: %08x"
+
+const char* messages[] =
+{"This error...........\n",
+ "That error...........\n",
+ "Problem..............\n",
+ "Something went wrong.\n",
+ "Everything ok........\n",
+ NULL
+};
+
+static int debug_test_format_fn(
+   debug_info_t * id, struct debug_view *view, 
+   char *out_buf, const char *in_buf
+)
+{
+  int i, rc = 0;
+
+  if(id->buf_size >= 4) {
+     int msg_nr = *((int*)in_buf);
+     if(msg_nr < sizeof(messages)/sizeof(char*) - 1)
+        rc += sprintf(out_buf, "%s", messages[msg_nr]);	
+     else
+        rc += sprintf(out_buf, UNKNOWNSTR, msg_nr);
+  }
+ out:
+   return rc;
+}
+
+struct debug_view debug_test_view = {
+  "myview",                 /* name of view */
+  NULL,                     /* no prolog */
+  &debug_dflt_header_fn,    /* default header for each entry */
+  &debug_test_format_fn,    /* our own format function */
+  NULL,                     /* no input function */
+  NULL                      /* no private data */
+};
+
+=====
+test:
+=====
+debug_info_t *debug_info;
+...
+debug_info = debug_register ("test", 0, 4, 4 ));
+debug_register_view(debug_info, &debug_test_view);
+for(i = 0; i < 10; i ++) debug_int_event(debug_info, 1, i);
+
+> cat /proc/s390dbf/test/myview
+00 00964419734:611402 1 - 00 88042ca   This error...........
+00 00964419734:611405 1 - 00 88042ca   That error...........
+00 00964419734:611408 1 - 00 88042ca   Problem..............
+00 00964419734:611411 1 - 00 88042ca   Something went wrong.
+00 00964419734:611414 1 - 00 88042ca   Everything ok........
+00 00964419734:611417 1 - 00 88042ca   data: 00000005
+00 00964419734:611419 1 - 00 88042ca   data: 00000006
+00 00964419734:611422 1 - 00 88042ca   data: 00000007
+00 00964419734:611425 1 - 00 88042ca   data: 00000008
+00 00964419734:611428 1 - 00 88042ca   data: 00000009
diff -u --recursive --new-file v2.4.3/linux/Documentation/scsi-generic.txt linux/Documentation/scsi-generic.txt
--- v2.4.3/linux/Documentation/scsi-generic.txt	Thu Feb  8 16:32:44 2001
+++ linux/Documentation/scsi-generic.txt	Thu Apr 12 12:03:50 2001
@@ -1,6 +1,6 @@
-            Notes on Linux's SG driver version 2.1.36
+            Notes on Linux's SG driver version 2.1.39
             -----------------------------------------
-                                                        20000110
+                                                        20010329
 
 Introduction
 ============
@@ -12,7 +12,7 @@
 amongst other things.
 
 These are notes on the Linux SCSI generic packet device driver (sg)
-describing version 2.1.36 . The original driver was written by Lawrence
+describing version 2.1.39 . The original driver was written by Lawrence
 Foard and remained in place with minimal changes since circa 1992.
 Version 2 of this driver remains backward compatible (binary and
 source **) with the original. It adds scatter gather, command queuing,
@@ -23,6 +23,10 @@
 at the linux/Documentation directory. The full document can be found
 at http://www.torque.net/sg/p/scsi-generic_long.txt .
 
+The Linux 2.4 series kernels have now been released. Lk 2.4 contains
+an upgraded "version 3" sg driver which is described in a supplementary
+document at http://www.torque.net/sg/p/scsi-generic_v3.txt .
+
 The interface and usage of the original sg driver have been documented
 by Heiko Eissfeldt in a HOWTO called SCSI-Programming-HOWTO. My copy
 of the document is version 1.5 dated 7th May 1996. It can found at
@@ -41,7 +45,8 @@
 The SCSI generic packet device driver (sg) is a character based device.
 It is one of the four high level device driver in the SCSI sub-system;
 the others are sd (for direct-access devices - disks), st (for tapes)
-and sr (for data cdroms). The other three devices are block devices.
+and sr (for data cdroms). Sd and sr are block devices while st (like sg)
+is a character device.
 
 The unifying layer of the SCSI sub-system is the so-called mid-level.
 Below that are the "low level" drivers which are the drivers for the
@@ -236,10 +241,11 @@
 /dev/sg[a-z]
 /dev/sg[0,1,2,...]
 or a symbolic link to one of these. [Devfs has its own sub-directory for
-sg devices with entries like: /dev/sg/c1b2t3u4 .] It seems as though SCSI
-devices are allocated to sg minor numbers in the same order as they appear
-in 'cat /proc/scsi/scsi'. Sg is a "character" based Linux device driver.
-This means it has an open/close/read/write/ioctl type interface.
+sg devices with entries like: /dev/scsi/host1/bus2/target3/lun4/generic .]
+It seems as though SCSI devices are allocated to sg minor numbers in the
+same order as they appear in 'cat /proc/scsi/scsi'. Sg is a "character"
+based Linux device driver.  This means it has an open/close/read/write/ioctl
+type interface.
 
 Flags can be either O_RDONLY or O_RDWR or-ed with either
 O_EXCL          waits for other opens on sg device to be closed before
@@ -396,7 +402,7 @@
 (which is called 'sg_release()' in the version 2 driver) to facilitate
 the cleanup mentioned above.
 
-A problem persists in version 2.1.36 if the sg driver is a module and is
+A problem persists in version 2.1.39 if the sg driver is a module and is
 removed while packets are still "in flight".
 
 Returns 0 if successful, otherwise -1 implies an error.
@@ -595,6 +601,8 @@
 do much (may in the future after other issues are resolved). Yields an
 EBUSY error if the SCSI bus or the associated device is being reset
 when this ioctl() is called, otherwise returns 0.
+N.B. In some recent distributions there is a patch to the SCSI mid level
+code that activates this ioctl. Check your distribution.
 
 SG_SET_DEBUG +:
 Assumes 3rd argument is pointing to an int. 0 (default) turns debugging
@@ -640,7 +648,7 @@
 found, switching to normal blocked io. A working example of this logic
 is in the sg_scan utility program.
 
-open("/dev/sga", O_RDONLY | O_NONBLOCK)
+open("/dev/sg0", O_RDONLY | O_NONBLOCK)
 /* check device, EBUSY means some other process has O_EXCL lock on it */
 /* when the device you want is found then ... */
 flags = fcntl(sg_fd, F_GETFL)
diff -u --recursive --new-file v2.4.3/linux/Documentation/sound/PAS16 linux/Documentation/sound/PAS16
--- v2.4.3/linux/Documentation/sound/PAS16	Sun Apr  2 15:38:53 2000
+++ linux/Documentation/sound/PAS16	Wed Apr 11 19:02:27 2001
@@ -1,7 +1,7 @@
 Pro Audio Spectrum 16 for 2.3.99 and later
 =========================================
 by Thomas Molina (tmolina@home.com)
-last modified 26 Mar 2000
+last modified 3 Mar 2001
 Acknowledgement to Axel Boldt (boldt@math.ucsb.edu) for stuff taken
 from Configure.help, Riccardo Facchetti for stuff from README.OSS,
 and others whose names I could not find.
@@ -48,14 +48,6 @@
           if you want to use the SB emulation of PAS16. It's also possible to
           the emulation if you want to use a true SB card together with PAS16
           (there is another question about this that is asked later).
-  "Sound Blaster support",
-        - Answer 'y' if you have an original SB card made by Creative Labs
-          or a full 100% hardware compatible clone (like Thunderboard or
-          SM Games). If your card was in the list of supported cards (above),
-          please look at the card specific instructions later in this file
-          before answering this question. For an unknown card you may answer
-          'y' if the card claims to be SB compatible.
-         Enable this option also with PAS16.
 
   "Generic OPL2/OPL3 FM synthesizer support",
         - Answer 'y' if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
@@ -113,27 +105,13 @@
   Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio
   16 or Logitech SoundMan 16 sound card. Don't answer Y if you have
   some other card made by Media Vision or Logitech since they are not
-  PAS16 compatible.
+  PAS16 compatible.  It is not necessary to enable the  separate
+  Sound Blaster support; it is included in the PAS driver.
+
   If you compile the driver into the kernel, you have to add
   "pas2=<io>,<irq>,<dma>,<dma2>,<sbio>,<sbirq>,<sbdma>,<sbdma2>
   to the kernel command line.
 
-100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support
-CONFIG_SOUND_SB
-  Answer Y if you have an original Sound Blaster card made by Creative
-  Labs or a 100% hardware compatible clone (like the Thunderboard or
-  SM Games). For an unknown card you may answer Y if the card claims
-  to be Sound Blaster-compatible.  The PAS16 has 8-bit Soundblaster
-  support, so you can answer Y here for it.
-
-  Please read the file Documentation/sound/Soundblaster.
-
-  If you compile the driver into the kernel and don't want to use isapnp,
-  you have to add "sb=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
-
-  You can say M here to compile this driver as a module; the module is
-  called sb.o.
-
 FM Synthesizer (YM3812/OPL-3) support
 CONFIG_SOUND_YM3812
   Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
@@ -167,7 +145,7 @@
 CONFIG_SOUND_TRACEINIT=y
 CONFIG_SOUND_DMAP=y
 CONFIG_SOUND_PAS=y
-CONFIG_SOUND_SB=y
+CONFIG_SOUND_SB=n
 CONFIG_SOUND_YM3812=m
 
 I have also included the following append line in /etc/lilo.conf:
diff -u --recursive --new-file v2.4.3/linux/Documentation/sound/PCM1-pro linux/Documentation/sound/PCM1-pro
--- v2.4.3/linux/Documentation/sound/PCM1-pro	Mon Apr 12 16:18:27 1999
+++ linux/Documentation/sound/PCM1-pro	Wed Dec 31 16:00:00 1969
@@ -1,17 +0,0 @@
-In Documentation/sound/README.OSS was a remark saying noone was sure the
-mixer on the PCM1-pro worked with the ACI driver. Well, it does.
-I've been using the drivers for the MAD16 and the driver for the mixer
-since kernel 2.0.32 with a MiroSound PCM1-pro and it works great.
-
-I've got it working with the following configuration:
-
-MAD16 audio I/O base = 530
-MAD16  audio IRQ = 7
-MAD16 Audio DMA = 1
-MAD16 MIDI I/O = 330
-MAD16 MIDI IRQ = 9
-
-And I've enabled the ACI mixer (miro PCM12) .
-
-
-Bas van der Linden.
diff -u --recursive --new-file v2.4.3/linux/Documentation/sound/README.OSS linux/Documentation/sound/README.OSS
--- v2.4.3/linux/Documentation/sound/README.OSS	Fri Jul 28 12:50:52 2000
+++ linux/Documentation/sound/README.OSS	Wed Apr 11 19:02:27 2001
@@ -17,6 +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 ]
 
 OSS/Free version 3.8 release notes
 ----------------------------------
@@ -1325,26 +1326,38 @@
 miroSOUND
 ---------
 
-The miroSOUND PCM12 has been used successfully. This card is 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 PCM12 and other MAD16 cards is that instead of the mixer in the
-CS4231 codec a separate mixer controlled by an on-board 80C32
-microcontroller is used. Control of the mixer takes place via the ACI
-(miro's audio control interface) protocol that is implemented in a
-separate lowlevel driver. Make sure you compile this ACI driver
-together with the normal MAD16 support when you use a miroSOUND PCM12
-card. The ACI mixer is controlled by /dev/mixer and the CS4231 mixer
-by /dev/mixer2. You usually don't want to change anything on the
-CS4231 mixer.
-
-The miroSOUND PCM12 is capable of full duplex operation (simultaneous
-PCM replay and recording), which allows you to implement nice
-real-time signal processing audio effect software and network
-telephones. The ACI mixer has to be configured into a special "solo"
+The miroSOUND PCM1-pro, PCM12 and PCM20 radio has been used
+successfully. This card is 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
+controlled by an on-board 80C32 microcontroller is used. Control of
+the mixer takes place via the ACI (miro's audio control interface)
+protocol that is implemented in a separate lowlevel driver. Make sure
+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.
+
+The miroSOUND PCM12 and PCM20 radio is capable of full duplex
+operation (simultaneous PCM replay and recording), which allows you to
+implement nice real-time signal processing audio effect software and
+network telephones. The ACI mixer has to be switched into the "solo"
 mode for duplex operation in order to avoid feedback caused by the
-mixer (input hears output signal). See lowlevel/aci.c for details on
-the ioctl() for activating the "solo" mode.
+mixer (input hears output signal). You can de-/activate this mode
+through toggleing the record button for the wave controller with an
+OSS-mixer.
+
+The PCM20 contains a radio tuner, which is also controlled by
+ACI. This radio tuner is supported by the ACI driver together with the
+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
+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.
 
 The following configuration parameters have worked fine for the PCM12
 in Markus Kuhn's system, many other configurations might work, too:
@@ -1352,13 +1365,8 @@
 CONFIG_MAD16_DMA2=0, CONFIG_MAD16_MPU_BASE=0x330, CONFIG_MAD16_MPU_IRQ=10,
 DSP_BUFFSIZE=65536, SELECTED_SOUND_OPTIONS=0x00281000.
 
-The miroSOUND PCM1 pro and the PCM20 are very similar to the PCM12.
-Perhaps the same ACI driver also works for these cards, however this
-has never actually been tested. The PCM20 contains a radio tuner,
-which is also controlled by ACI. This radio tuner is currently not
-supported by the ACI driver, but documentation for it was provided by
-miro and ACI tuner support could easily be added if someone is really
-interested.
+Bas van der Linden is using his PCM1-pro with a configuration that
+differs in: CONFIG_MAD16_IRQ=7, CONFIG_MAD16_DMA=1, CONFIG_MAD16_MPU_IRQ=9
 
 Compaq Deskpro XL
 -----------------
diff -u --recursive --new-file v2.4.3/linux/Documentation/sound/es1370 linux/Documentation/sound/es1370
--- v2.4.3/linux/Documentation/sound/es1370	Fri Jul 10 14:03:35 1998
+++ linux/Documentation/sound/es1370	Wed Apr 11 19:02:27 2001
@@ -1,3 +1,11 @@
+/proc/sound, /dev/sndstat
+-------------------------
+
+/proc/sound and /dev/sndstat is not supported by the
+driver. To find out whether the driver succeeded loading,
+check the kernel log (dmesg).
+
+
 ALaw/uLaw sample formats
 ------------------------
 
@@ -59,4 +67,4 @@
 
 
 Thomas Sailer
-sailer@ife.ee.ethz.ch
+t.sailer@alumni.ethz.ch
diff -u --recursive --new-file v2.4.3/linux/Documentation/sound/es1371 linux/Documentation/sound/es1371
--- v2.4.3/linux/Documentation/sound/es1371	Fri Jul 10 14:03:35 1998
+++ linux/Documentation/sound/es1371	Wed Apr 11 19:02:27 2001
@@ -1,3 +1,11 @@
+/proc/sound, /dev/sndstat
+-------------------------
+
+/proc/sound and /dev/sndstat is not supported by the
+driver. To find out whether the driver succeeded loading,
+check the kernel log (dmesg).
+
+
 ALaw/uLaw sample formats
 ------------------------
 
@@ -53,4 +61,4 @@
 
 
 Thomas Sailer
-sailer@ife.ee.ethz.ch
+t.sailer@alumni.ethz.ch
diff -u --recursive --new-file v2.4.3/linux/Documentation/sound/solo1 linux/Documentation/sound/solo1
--- v2.4.3/linux/Documentation/sound/solo1	Mon Aug 23 11:15:27 1999
+++ linux/Documentation/sound/solo1	Wed Apr 11 19:02:27 2001
@@ -1,3 +1,25 @@
+Recording
+---------
+
+Recording does not work on the author's card, but there
+is at least one report of it working on later silicon.
+The chip behaves differently than described in the data sheet,
+likely due to a chip bug. Working around this would require
+the help of ESS (for example by publishing an errata sheet),
+but ESS has not done so so far.
+
+Also, the chip only supports 24 bit addresses for recording,
+which means it cannot work on some Alpha mainboards.
+
+
+/proc/sound, /dev/sndstat
+-------------------------
+
+/proc/sound and /dev/sndstat is not supported by the
+driver. To find out whether the driver succeeded loading,
+check the kernel log (dmesg).
+
+
 ALaw/uLaw sample formats
 ------------------------
 
@@ -45,4 +67,4 @@
 The card has an OPL compatible FM synthesizer.
 
 Thomas Sailer
-sailer@ife.ee.ethz.ch
+t.sailer@alumni.ethz.ch
diff -u --recursive --new-file v2.4.3/linux/Documentation/sound/sonicvibes linux/Documentation/sound/sonicvibes
--- v2.4.3/linux/Documentation/sound/sonicvibes	Fri Jul 10 14:03:35 1998
+++ linux/Documentation/sound/sonicvibes	Wed Apr 11 19:02:27 2001
@@ -1,3 +1,11 @@
+/proc/sound, /dev/sndstat
+-------------------------
+
+/proc/sound and /dev/sndstat is not supported by the
+driver. To find out whether the driver succeeded loading,
+check the kernel log (dmesg).
+
+
 ALaw/uLaw sample formats
 ------------------------
 
@@ -70,4 +78,4 @@
 
 
 Thomas Sailer
-sailer@ife.ee.ethz.ch
+t.sailer@alumni.ethz.ch
diff -u --recursive --new-file v2.4.3/linux/MAINTAINERS linux/MAINTAINERS
--- v2.4.3/linux/MAINTAINERS	Sun Mar 25 18:14:20 2001
+++ linux/MAINTAINERS	Wed Apr 25 14:35:25 2001
@@ -106,6 +106,13 @@
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
+ACI MIXER DRIVER
+P:	Robert Siemer
+M:	Robert.Siemer@gmx.de
+L:	linux-sound@vger.kernel.org
+W:	http://www.uni-karlsruhe.de/~Robert.Siemer/Private/
+S:	Maintained
+
 ACPI
 P:	Andy Grover
 M:	andrew.grover@intel.com
@@ -133,6 +140,11 @@
 M:	fizban@tin.it
 S:	Maintained
 
+AFFS FILE SYSTEM
+P:	Roman Zippel
+M:	zippel@linux-m68k.org
+S:	Maintained
+
 AHA152X SCSI DRIVER
 P:	Juergen E. Fischer
 M:	Juergen Fischer <fischer@norbit.de>
@@ -141,9 +153,9 @@
 
 APM DRIVER
 P:	Stephen Rothwell
-M:	apm@linuxcare.com.au
+M:	sfr@canb.auug.org.au
 L:	linux-laptop@vger.kernel.org
-W:	http://linuxcare.com.au/apm/
+W:	http://www.canb.auug.org.au/~sfr/
 S:	Supported
 
 APPLETALK NETWORK LAYER
@@ -293,6 +305,13 @@
 M:	jam@acm.org
 S:	Maintained
 
+CRIS PORT
+P:	Bjorn Wesen
+M:	bjornw@axis.com
+L:	dev-etrax@axis.com
+W:	http://developer.axis.com
+S:	Maintained
+
 CYBERPRO FB DRIVER
 P:	Russell King
 M:	linux@arm.linux.org.uk
@@ -368,7 +387,7 @@
 
 DIRECTORY NOTIFICATION
 P:	Stephen Rothwell
-M:	sfr@linuxcare.com.au
+M:	sfr@canb.auug.org.au
 L:	linux-kernel@vger.kernel.org
 S:	Supported
 
@@ -398,6 +417,12 @@
 L:	dri-devel@lists.sourceforge.net
 S:	Supported
 
+DSCC4 DRIVER
+P:	François Romieu
+M:	romieu@cogenit.fr
+M:	romieu@ensta.fr
+S:	Maintained
+
 EATA-DMA SCSI DRIVER
 P:	Michael Neuffer
 M:	mike@i-Connect.Net
@@ -490,6 +515,12 @@
 W:	http://www.icp-vortex.com/
 S:	Supported
 
+GENERIC HDLC DRIVER, N2 AND C101 DRIVERS
+P:	Krzysztof Halasa
+M:	khc@pm.waw.pl
+W:	http://hq.pm.waw.pl/hdlc/
+S:	Maintained
+
 HAYES ESP SERIAL DRIVER
 P:	Andrew J. Robinson
 M:	arobinso@nyx.net
@@ -535,7 +566,7 @@
 
 HIPPI
 P:	Jes Sorensen
-M:	Jes.Sorensen@cern.ch
+M:	jes@linuxcare.com
 L:	linux-hippi@sunsite.auc.dk
 S:	Maintained
 
@@ -600,7 +631,14 @@
 W:	http://www.kernel.dk
 S:	Maintained
 
-IDE/ATAPI TAPE/FLOPPY DRIVERS
+IDE/ATAPI FLOPPY DRIVERS
+P:	Paul Bristow
+M:	Paul Bristow <paul@paulbristow.net>
+W:	http://paulbristow.net/linux/idefloppy.html
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
+IDE/ATAPI TAPE DRIVERS
 P:	Gadi Oxman
 M:	Gadi Oxman <gadio@netvision.net.il>
 L:	linux-kernel@vger.kernel.org
@@ -750,14 +788,14 @@
 
 LINUX FOR POWER MACINTOSH
 P:	Paul Mackerras
-M:	paulus@linuxcare.com
+M:	paulus@samba.org
 W:	http://www.linuxppc.org/
 L:	linuxppc-dev@lists.linuxppc.org
 S:	Maintained
 
 M68K
 P:	Jes Sorensen
-M:	Jes.Sorensen@cern.ch
+M:	jes@linuxcare.com
 W:	http://www.clark.net/pub/lawrencc/linux/index.html
 L:	linux-m68k@lists.linux-m68k.org
 S:	Maintained
@@ -775,7 +813,7 @@
 W:	http://www.tazenda.demon.co.uk/phil/linux-hp
 S:	Maintained
 
-MAESTRO PCI SOUND DRIVER
+MAESTRO PCI SOUND DRIVERS
 P:	Zach Brown
 M:	zab@zabbo.net
 S:	Odd Fixes
@@ -787,6 +825,12 @@
 L:	mtd@infradead.org
 S:	Maintained
 
+MICROTEK X6 SCANNER
+P:      Oliver Neukum
+M:      drivers@neukum.org
+W:      http://fachschaft.cup.uni-muenchen.de/~neukum/scanner.html
+S:      Maintained
+
 MIPS
 P:	Ralf Baechle
 M:	ralf@gnu.ai.mit.edu
@@ -837,10 +881,14 @@
 
 NETFILTER
 P:	Rusty Russell
-M:	rusty@linuxcare.com
+M:	rusty@rustcorp.com.au
 P:	Marc Boucher
 M:	marc@mbsi.ca
-W:	http://www.samba.org/netfilter/
+P:	James Morris
+M:	jamesm@intercode.com.au
+P:	Harald Welte
+M:	laforge@gnumonks.org
+W:	http://netfilter.samba.org
 W:	http://netfilter.kernelnotes.org
 W:	http://netfilter.filewatcher.org
 L:	netfilter@lists.samba.org
@@ -904,8 +952,9 @@
 NTFS FILESYSTEM
 P:	Anton Altaparmakov
 M:	aia21@cus.cam.ac.uk
+L:	linux-ntfs-dev@lists.sourceforge.net
 L:	linux-kernel@vger.kernel.org
-S:	Odd Fixes
+S:	Maintained
 
 NVIDIA (RIVA) FRAMEBUFFER DRIVER
 P:	Ani Joshi
@@ -917,9 +966,9 @@
 P:	Peter De Shrijver
 M:	p2@ace.ulyssis.sutdent.kuleuven.ac.be	
 P:	Mike Phillips
-M:	phillim@amtrak.com
+M:	mikep@linuxtr.net 
 L:	linux-net@vger.kernel.org
-L:	linux-tr@emissary.aus-etc.com
+L:	linux-tr@linuxtr.net
 W:	http://www.linuxtr.net
 S:	Maintained
 
@@ -997,7 +1046,7 @@
 
 PPP PROTOCOL DRIVERS AND COMPRESSORS
 P:	Paul Mackerras
-M:	paulus@linuxcare.com
+M:	paulus@samba.org
 L:	linux-ppp@vger.kernel.org
 S:	Maintained
 
@@ -1037,6 +1086,13 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
+REISERFS FILE SYSTEM
+P:      Hans Reiser
+M:      reiserfs-dev@namesys.com
+L:      reiserfs-list@namesys.com
+W:      http://www.namesys.com
+S:      Supported
+
 ROSE NETWORK LAYER
 P:	Jean-Paul Roubelat
 M:	jpr@f6fbb.org
@@ -1056,6 +1112,14 @@
 W:	www.rtlinux.org
 S:	Maintained
 
+S390
+P:	Martin Schwidefsky
+M:	schwidefsky@de.ibm.com
+M:	linux390@de.ibm.com
+L:	linux-390@vm.marist.edu
+W:	http://oss.software.ibm.com/developerworks/opensource/linux390
+S:	Supported
+
 SA1100 SUPPORT
 P:	Nicolas Pitre
 M:	nico@cam.org
@@ -1174,6 +1238,11 @@
 W:	http://www.stallion.com
 S:	Supported
 
+STARFIRE/DURALAN NETWORK DRIVER
+P:	Ion Badulescu
+M:	ionut@cs.columbia.edu
+S:	Maintained
+
 STARMODE RADIO IP (STRIP) PROTOCOL DRIVER
 W:	http://mosquitonet.Stanford.EDU/strip.html
 S:	Unsupported ?
@@ -1357,11 +1426,11 @@
 
 USB SERIAL KEYSPAN DRIVER
 P:	Hugh Blemings
-M:	hugh@linuxcare.com
+M:	hugh@misc.nu
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
-W:	http://www.linuxcare.com.au/hugh/keyspan.html
+W:	http://misc.nu/hugh/keyspan/
 
 USB SERIAL DRIVER
 P:	Greg Kroah-Hartman
@@ -1430,8 +1499,8 @@
 S:	Maintained for 2.2 only
 
 WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
-P:     Jaspreet Singh
-M:     jaspreet@sangoma.com
+P:     Nenad Corbic
+M:     ncorbic@sangoma.com
 M:     dm@sangoma.com
 W:     http://www.sangoma.com
 S:     Supported
@@ -1457,6 +1526,12 @@
 X86 3-LEVEL PAGING (PAE) SUPPORT
 P:	Ingo Molnar
 M:	mingo@redhat.com
+S:	Maintained
+
+YAM DRIVER FOR AX.25
+P:	Jean-Paul Roubelat
+M:	jpr@f6fbb.org
+L:	linux-hams@vger.kernel.org
 S:	Maintained
 
 Z85230 SYNCHRONOUS DRIVER
diff -u --recursive --new-file v2.4.3/linux/Makefile linux/Makefile
--- v2.4.3/linux/Makefile	Thu Mar 29 20:13:15 2001
+++ linux/Makefile	Mon Apr 23 15:29:21 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 3
-EXTRAVERSION =
+SUBLEVEL = 4
+EXTRAVERSION =-pre7
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -u --recursive --new-file v2.4.3/linux/REPORTING-BUGS linux/REPORTING-BUGS
--- v2.4.3/linux/REPORTING-BUGS	Mon Aug 21 08:57:35 2000
+++ linux/REPORTING-BUGS	Fri Apr  6 10:42:48 2001
@@ -25,10 +25,9 @@
 overlook things, and easier for the developers to find the pieces of 
 information they're really interested in. Don't feel you have to follow it.
 
-   First run the ver_linux script included as scripts/ver_linux or
-at <URL:ftp://ftp.sai.msu.su/pub/Linux/ver_linux> It checks out
-the version of some important subsystems.  Run it with the command
-"sh scripts/ver_linux"
+      First run the ver_linux script included as scripts/ver_linux, which
+reports the version of some important subsystems.  Run this script with
+the command "sh scripts/ver_linux".
 
 Use that information to fill in all fields of the bug report form, and
 post it to the mailing list with a subject of "PROBLEM: <one line
diff -u --recursive --new-file v2.4.3/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.4.3/linux/arch/alpha/config.in	Fri Dec 29 14:07:19 2000
+++ linux/arch/alpha/config.in	Tue Apr 17 17:19:24 2001
@@ -5,6 +5,8 @@
 
 define_bool CONFIG_ALPHA y
 define_bool CONFIG_UID16 n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Kernel configuration of Linux for Alpha machines"
 
diff -u --recursive --new-file v2.4.3/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.4.3/linux/arch/alpha/kernel/alpha_ksyms.c	Fri Mar  2 11:15:47 2001
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Fri Apr 20 18:26:15 2001
@@ -173,9 +173,6 @@
 EXPORT_SYMBOL(down_interruptible);
 EXPORT_SYMBOL(down_trylock);
 EXPORT_SYMBOL(up);
-EXPORT_SYMBOL(__down_read_failed);
-EXPORT_SYMBOL(__down_write_failed);
-EXPORT_SYMBOL(__rwsem_wake);
 EXPORT_SYMBOL(down_read);
 EXPORT_SYMBOL(down_write);
 EXPORT_SYMBOL(up_read);
@@ -190,7 +187,6 @@
 EXPORT_SYMBOL(synchronize_irq);
 EXPORT_SYMBOL(flush_tlb_all);
 EXPORT_SYMBOL(flush_tlb_mm);
-EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(flush_tlb_range);
 EXPORT_SYMBOL(smp_imb);
 EXPORT_SYMBOL(cpu_data);
diff -u --recursive --new-file v2.4.3/linux/arch/alpha/kernel/semaphore.c linux/arch/alpha/kernel/semaphore.c
--- v2.4.3/linux/arch/alpha/kernel/semaphore.c	Sun Nov 12 19:31:11 2000
+++ linux/arch/alpha/kernel/semaphore.c	Tue Apr 17 17:19:24 2001
@@ -263,185 +263,3 @@
 #endif
 	__up(sem);
 }
-
-
-/*
- * RW Semaphores
- */
-
-void
-__down_read_failed(struct rw_semaphore *sem, int count)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
- retry_down:
-	if (count < 0) {
-		/* Waiting on multiple readers and/or writers.  */
-		
-		/* Undo the acquisition we started in down_read.  */
-		atomic_inc(&sem->count);
-
-		current->state = TASK_UNINTERRUPTIBLE;
-		wmb();
-		add_wait_queue(&sem->wait, &wait);
-		mb();
-		while (atomic_read(&sem->count) < 0) {
-			schedule();
-			set_task_state(current, TASK_UNINTERRUPTIBLE);
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		current->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_dec_return(&sem->count);
-		if (count <= 0)
-			goto retry_down;
-	} else {
-		/* Waiting on exactly one writer.  */
-
-		current->state = TASK_UNINTERRUPTIBLE;
-		wmb();
-		add_wait_queue(&sem->wait, &wait);
-		mb();
-
-		while (!test_and_clear_bit(0, &sem->granted)) {
-			schedule();
-			set_task_state(current, TASK_UNINTERRUPTIBLE);
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		current->state = TASK_RUNNING;
-	}
-}
-
-void
-__down_write_failed(struct rw_semaphore *sem, int count)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
- retry_down:
-	if (count + RW_LOCK_BIAS < 0) {
-		/* Waiting on multiple readers and/or writers.  */
-
-		/* Undo the acquisition we started in down_write.  */
-		atomic_add(RW_LOCK_BIAS, &sem->count);
-
-		current->state = TASK_UNINTERRUPTIBLE;
-		wmb();
-		add_wait_queue_exclusive(&sem->wait, &wait);
-		mb();
-	
-		while (atomic_read(&sem->count) + RW_LOCK_BIAS < 0) {
-			schedule();
-			set_task_state(current, TASK_UNINTERRUPTIBLE);
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		current->state = TASK_RUNNING;
-
-		count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-		if (count != 0)
-			goto retry_down;
-	} else {
-		/* Waiting on exactly one writer.  */
-
-		current->state = TASK_UNINTERRUPTIBLE;
-		wmb();
-		add_wait_queue_exclusive(&sem->wait, &wait);
-		mb();
-
-		while (!test_and_clear_bit(1, &sem->granted)) {
-			schedule();
-			set_task_state(current, TASK_UNINTERRUPTIBLE);
-		}
-
-		remove_wait_queue(&sem->write_bias_wait, &wait);
-		current->state = TASK_RUNNING;
-
-		/* If the lock is currently unbiased, awaken the sleepers.
-		   FIXME: This wakes up the readers early in a bit of a
-		   stampede -> bad!  */
-		count = atomic_read(&sem->count);
-		if (__builtin_expect(count >= 0, 0))
-			wake_up(&sem->wait);
-	}
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, int readers)
-{
-	if (readers) {
-		if (test_and_set_bit(0, &sem->granted))
-			BUG();
-		wake_up(&sem->wait);
-	} else {
-		if (test_and_set_bit(1, &sem->granted))
-			BUG();
-		wake_up(&sem->write_bias_wait);
-	}
-}
-
-void
-down_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__down_read(sem);
-#if WAITQUEUE_DEBUG
-	if (sem->granted & 2)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-void
-down_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__down_write(sem);
-#if WAITQUEUE_DEBUG
-	if (sem->granted & 3)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-void
-up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-	if (sem->granted & 2)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-	__up_read(sem);
-}
-
-void
-up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-	if (sem->granted & 3)
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-	__up_write(sem);
-}
diff -u --recursive --new-file v2.4.3/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- v2.4.3/linux/arch/alpha/mm/init.c	Tue Nov 28 22:43:39 2000
+++ linux/arch/alpha/mm/init.c	Fri Apr 13 20:26:06 2001
@@ -43,20 +43,6 @@
 struct pgtable_cache_struct quicklists;
 #endif
 
-void
-__bad_pmd(pgd_t *pgd)
-{
-	printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
-	pgd_set(pgd, BAD_PAGETABLE);
-}
-
-void
-__bad_pte(pmd_t *pmd)
-{
-	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-	pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
-}
-
 pgd_t *
 get_pgd_slow(void)
 {
@@ -80,66 +66,26 @@
 	return ret;
 }
 
-pmd_t *
-get_pmd_slow(pgd_t *pgd, unsigned long offset)
-{
-	pmd_t *pmd;
-
-	pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
-	if (pgd_none(*pgd)) {
-		if (pmd) {
-			clear_page((void *)pmd);
-			pgd_set(pgd, pmd);
-			return pmd + offset;
-		}
-		pgd_set(pgd, BAD_PAGETABLE);
-		return NULL;
-	}
-	free_page((unsigned long)pmd);
-	if (pgd_bad(*pgd)) {
-		__bad_pmd(pgd);
-		return NULL;
-	}
-	return (pmd_t *) pgd_page(*pgd) + offset;
-}
-
-pte_t *
-get_pte_slow(pmd_t *pmd, unsigned long offset)
-{
-	pte_t *pte;
-
-	pte = (pte_t *) __get_free_page(GFP_KERNEL);
-	if (pmd_none(*pmd)) {
-		if (pte) {
-			clear_page((void *)pte);
-			pmd_set(pmd, pte);
-			return pte + offset;
-		}
-		pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
-		return NULL;
-	}
-	free_page((unsigned long)pte);
-	if (pmd_bad(*pmd)) {
-		__bad_pte(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + offset;
-}
-
 int do_check_pgt_cache(int low, int high)
 {
 	int freed = 0;
-        if(pgtable_cache_size > high) {
-                do {
-                        if(pgd_quicklist)
-                                free_pgd_slow(get_pgd_fast()), freed++;
-                        if(pmd_quicklist)
-                                free_pmd_slow(get_pmd_fast()), freed++;
-                        if(pte_quicklist)
-                                free_pte_slow(get_pte_fast()), freed++;
-                } while(pgtable_cache_size > low);
-        }
-        return freed;
+	if(pgtable_cache_size > high) {
+		do {
+			if(pgd_quicklist) {
+				free_pgd_slow(get_pgd_fast());
+				freed++;
+			}
+			if(pmd_quicklist) {
+				pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
+				freed++;
+			}
+			if(pte_quicklist) {
+				pte_free_slow(pte_alloc_one_fast(NULL, 0));
+				freed++;
+			}
+		} while(pgtable_cache_size > low);
+	}
+	return freed;
 }
 
 /*
diff -u --recursive --new-file v2.4.3/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.4.3/linux/arch/arm/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/Makefile	Thu Apr 12 12:20:31 2001
@@ -1,52 +1,36 @@
 #
 # arch/arm/Makefile
 #
-# This file is included by the global makefile so that you can add your own
-# architecture-specific flags and dependencies. Remember to do have actions
-# for "archclean" and "archdep" for cleaning up and making dependencies for
-# this architecture
-#
 # This file is subject to the terms and conditions of the GNU General Public
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1995-2000 by Russell King
+# Copyright (C) 1995-2001 by Russell King
 
 LINKFLAGS	:=-p -X -T arch/arm/vmlinux.lds
 GZFLAGS		:=-9
 CFLAGS		+=-fno-common -pipe
 
-ifdef CONFIG_FRAME_POINTER
+ifneq ($(CONFIG_NO_FRAME_POINTER),y)
 CFLAGS		:=$(CFLAGS:-fomit-frame-pointer=)
 endif
 
-ifdef CONFIG_DEBUG_INFO
+ifeq ($(CONFIG_DEBUG_INFO),y)
 CFLAGS		+=-g
 endif
 
-# Ensure this is ld "2.9.4" or later
-NEW_LINKER	:= $(shell $(LD) --gc-sections --version >/dev/null 2>&1; echo $$?)
-
-ifneq ($(NEW_LINKER),0)
-dummy:;		@echo '*** ${VERSION}.${PATCHLEVEL} kernels no longer build correctly with old versions of binutils.'
-		@echo '*** Please upgrade your binutils to 2.9.5.'
-		@false
-endif
-
 # Select CPU dependent flags.  Note that order of declaration is important;
 # the options further down the list override previous items.
 #
-apcs-$(CONFIG_CPU_26)		:=-mapcs-26 -mcpu=arm3 -Os
-apcs-$(CONFIG_CPU_32)		:=-mapcs-32
+apcs-y				:=
+apcs-$(CONFIG_CPU_26)		:=-mcpu=arm3 -Os
 
-arch-$(CONFIG_CPU_32v3)		:=-march=armv3
+arch-y				:=
+arch-$(CONFIG_CPU_32v3)		:=-march=armv3m
 arch-$(CONFIG_CPU_32v4)		:=-march=armv4
 arch-$(CONFIG_CPU_32v5)		:=-march=armv5
 
-proc-$(CONFIG_CPU_32v3)		:=-marmv3m
-proc-$(CONFIG_CPU_32v4)		:=-marmv4
-proc-$(CONFIG_CPU_32v5)		:=-marmv5
-
+tune-y				:=
 tune-$(CONFIG_CPU_ARM610)	:=-mtune=arm610
 tune-$(CONFIG_CPU_ARM710)	:=-mtune=arm710
 tune-$(CONFIG_CPU_ARM720T)	:=-mtune=arm7tdmi
@@ -54,19 +38,27 @@
 tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
 
-CFLAGS		+= $(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
-AFLAGS		+= $(apcs-y) $(proc-y) -mno-fpu
+CFLAGS		+= -mapcs-32 $(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
+AFLAGS		+= -mapcs-32 $(apcs-y) $(arch-y) -mno-fpu
 
 LIBGCC		:= $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
 
 ifeq ($(CONFIG_CPU_26),y)
 PROCESSOR	 = armo
-TEXTADDR	 = 0x02080000
+  ifeq ($(CONFIG_ROM_KERNEL),y)
+    DATAADDR	 = 0x02080000
+    TEXTADDR	 = 0x03800000
+    LDSCRIPT	 = arch/arm/vmlinux-armo-rom.lds.in
+  else
+    TEXTADDR	 = 0x02080000
+    LDSCRIPT	 = arch/arm/vmlinux-armo.lds.in
+  endif
 endif
 
 ifeq ($(CONFIG_CPU_32),y)
 PROCESSOR	 = armv
 TEXTADDR	 = 0xC0008000
+LDSCRIPT	 = arch/arm/vmlinux-armv.lds.in
 endif
 
 ifeq ($(CONFIG_ARCH_ARCA5K),y)
@@ -97,8 +89,13 @@
 INCDIR		 = ebsa285
 endif
 
-ifeq ($(CONFIG_ARCH_NEXUSPCI),y)
-MACHINE		 = nexuspci
+ifeq ($(CONFIG_ARCH_FTVPCI),y)
+MACHINE		 = ftvpci
+INCDIR		 = nexuspci
+endif
+
+ifeq ($(CONFIG_ARCH_TBOX),y)
+MACHINE		 = tbox
 endif
 
 ifeq ($(CONFIG_ARCH_SHARK),y)
@@ -134,6 +131,10 @@
 INCDIR		:= $(MACHINE)
 endif
 
+ifeq ($(origin DATAADDR), undefined)
+DATAADDR	:= .
+endif
+
 # If we have a machine-specific directory, then include it in the build.
 MACHDIR		:= arch/arm/mach-$(MACHINE)
 ifeq ($(MACHDIR),$(wildcard $(MACHDIR)))
@@ -143,13 +144,17 @@
 
 HEAD		:= arch/arm/kernel/head-$(PROCESSOR).o \
 		   arch/arm/kernel/init_task.o
-SUBDIRS		+= arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe
+SUBDIRS		+= arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe \
+		   arch/arm/fastfpe
 CORE_FILES	:= arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
-LIBS		:= arch/arm/lib/lib.o arch/arm/lib/lib.a $(LIBS) $(LIBGCC)
+LIBS		:= arch/arm/lib/lib.a $(LIBS) $(LIBGCC)
 
-ifeq ($(CONFIG_NWFPE),y)
+ifeq ($(CONFIG_FPE_NWFPE),y)
 LIBS		:= arch/arm/nwfpe/math-emu.o $(LIBS)
 endif
+ifeq ($(CONFIG_FPE_FASTFPE),y)
+LIBS		:= arch/arm/fastfpe/fast-math-emu.o $(LIBS)
+endif
 
 ifeq ($(CONFIG_ARCH_CLPS7500),y)
 SUBDIRS		+= drivers/acorn/char
@@ -157,21 +162,13 @@
 endif
 
 MAKEBOOT	 = $(MAKE) -C arch/$(ARCH)/boot
+MAKETOOLS	 = $(MAKE) -C arch/$(ARCH)/tools
 
 # The following is a hack to get 'constants.h' up
 # to date before starting compilation
 
-$(patsubst %, _dir_%, $(SUBDIRS)) init/main.o init/version.o : \
-	include/asm-arm/mach-types.h
-
-$(patsubst %, _dir_%, $(SUBDIRS)) : constants
-
-include/asm-arm/mach-types.h: arch/arm/tools/mach-types  \
-			      arch/arm/tools/gen-mach-types
-	@awk -f arch/arm/tools/gen-mach-types arch/arm/tools/mach-types > $@
-
-constants: dummy
-	@$(MAKE) -C arch/arm/lib constants.h
+$(patsubst %,_dir_%, $(SUBDIRS)): maketools
+$(patsubst %,_modsubdir_%,$(MOD_DIRS)): maketools
 
 symlinks: archsymlinks
 
@@ -181,8 +178,8 @@
 
 vmlinux: arch/arm/vmlinux.lds
 
-arch/arm/vmlinux.lds: arch/arm/vmlinux-$(PROCESSOR).lds.in dummy
-	@sed 's/TEXTADDR/$(TEXTADDR)/' <$< >$@
+arch/arm/vmlinux.lds: $(LDSCRIPT) dummy
+	@sed 's/TEXTADDR/$(TEXTADDR)/;s/DATAADDR/$(DATAADDR)/' $(LDSCRIPT) >$@
 
 arch/arm/kernel arch/arm/mm arch/arm/lib: dummy
 	$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@)
@@ -190,17 +187,42 @@
 bzImage zImage zinstall Image bootpImage install: vmlinux
 	@$(MAKEBOOT) $@
 
+CLEAN_FILES	+= \
+	arch/arm/vmlinux.lds
+
+MRPROPER_FILES	+= \
+	include/asm-arm/arch \
+	include/asm-arm/proc \
+	include/asm-arm/constants.h* \
+	include/asm-arm/mach-types.h
+
+# We use MRPROPER_FILES and CLEAN_FILES now
 archmrproper:
-	$(RM) include/asm-arm/arch include/asm-arm/proc
+	@/bin/true
 
 archclean:
 	@$(MAKEBOOT) clean
-	$(RM) arch/arm/lib/constants.h arch/arm/vmlinux.lds
-	$(RM) include/asm-arm/mach-types.h
 
-archdep: archsymlinks
+archdep: scripts/mkdep archsymlinks
+	@$(MAKETOOLS) dep
 	@$(MAKEBOOT) dep
 
+maketools: checkbin
+	@$(MAKETOOLS) all
+
+# Ensure this is ld "2.9.4" or later
+NEW_LINKER	:= $(shell $(LD) --gc-sections --version >/dev/null 2>&1; echo $$?)
+
+ifneq ($(NEW_LINKER),0)
+checkbin:
+	@echo '*** ${VERSION}.${PATCHLEVEL} kernels no longer build correctly with old versions of binutils.'
+	@echo '*** Please upgrade your binutils to 2.9.5.'
+	@false
+else
+checkbin:
+	@true
+endif
+
 # My testing targets (that short circuit a few dependencies)
 zImg:;	@$(MAKEBOOT) zImage
 Img:;	@$(MAKEBOOT) Image
@@ -211,15 +233,7 @@
 #
 # Configuration targets.  Use these to select a
 # configuration for your architecture
-CFGS=	a5k_config		ebsa110_config		\
-	footbridge_config	rpc_config		\
-	brutus_config		victor_config		\
-	empeg_config		graphicsclient_config	\
-	assabet_config		lart_config		\
-	cerf_config		lusl7200_config 	\
-	sherman_config		pangolin_config
-
-$(CFGS):
+%_config:
 	@( \
 	CFG=$(@:_config=); \
 	if [ -f arch/arm/def-configs/$$CFG ]; then \
diff -u --recursive --new-file v2.4.3/linux/arch/arm/boot/Makefile linux/arch/arm/boot/Makefile
--- v2.4.3/linux/arch/arm/boot/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/boot/Makefile	Thu Apr 12 12:03:50 2001
@@ -55,8 +55,7 @@
 endif
 
 ifeq ($(CONFIG_ARCH_NEXUSPCI),y)
-ZTEXTADDR	 = 0x40200000
-ZRELADDR	 = 0x40008000
+ZTEXTADDR	 = 0x40008000
 endif
 
 ifeq ($(CONFIG_ARCH_L7200),y)
@@ -72,7 +71,6 @@
 
 ifeq ($(CONFIG_ARCH_P720T),y)
 ZTEXTADDR	 = 0xc0018000
-ZRELADDR	 = 0xc0018000
 PARAMS_PHYS	 = 0xc0000100
 INITRD_PHYS	 = 0xc0400000
 INITRD_VIRT	 = 0xc0400000
diff -u --recursive --new-file v2.4.3/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile
--- v2.4.3/linux/arch/arm/boot/compressed/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/boot/compressed/Makefile	Thu Apr 12 12:03:50 2001
@@ -9,7 +9,7 @@
 
 HEAD		 = head.o
 OBJS		 = misc.o
-CFLAGS		 = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_PROC)
+CFLAGS		 = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_PROC) -msoft-float
 FONTC		 = $(TOPDIR)/drivers/video/font_acorn_8x8.c
 ZLDFLAGS	 = -p -X -T vmlinux.lds
 
@@ -25,16 +25,24 @@
 OBJS		+= head-netwinder.o
 endif
 
+ifeq ($(CONFIG_ARCH_SHARK),y)
+OBJS		+= head-shark.o ofw-shark.o
+endif
+
 ifeq ($(CONFIG_ARCH_INTEGRATOR),y)
 OBJS		+= head-netwinder.o
 endif
 
-ifeq ($(CONFIG_ARCH_NEXUSPCI),y)
-HEAD		 = head-nexuspci.o
+ifeq ($(CONFIG_ARCH_FTVPCI),y)
+OBJS		+= head-ftvpci.o
 endif
 
 ifeq ($(CONFIG_ARCH_L7200),y)
 OBJS		+= head-l7200.o
+endif
+
+ifeq ($(CONFIG_ARCH_CLPS7500),y)
+HEAD		= head-clps7500.o
 endif
 
 ifeq ($(CONFIG_ARCH_P720T),y)
diff -u --recursive --new-file v2.4.3/linux/arch/arm/boot/compressed/head-clps7500.S linux/arch/arm/boot/compressed/head-clps7500.S
--- v2.4.3/linux/arch/arm/boot/compressed/head-clps7500.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/boot/compressed/head-clps7500.S	Thu Apr 12 12:03:50 2001
@@ -0,0 +1,87 @@
+/*
+ * linux/arch/arm/boot/compressed/head.S
+ *
+ * Copyright (C) 1999, 2000, 2001 Nexus Electronics Ltd
+ */
+
+#include <linux/config.h>
+
+		/* There are three different ways the kernel can be
+		   booted on a 7500 system: from Angel (loaded in RAM), from
+		   16-bit ROM or from 32-bit Flash.  Luckily, a single kernel
+		   image does for them all. */
+		/* This branch is taken if the CPU memory width matches the
+		   actual device in use.  The default at power on is 16 bits
+		   so we must be prepared for a mismatch. */
+		.section ".start", #alloc, #execinstr
+2:
+		b	1f
+		.word	0xffff
+		.word	0xb632		@ mov r11, #0x03200000
+		.word	0xe3a0
+		.word	0x0000		@ mov r0, #0
+		.word	0xe3a0
+		.word	0x0080		@ strb r0, [r11, #0x80]
+		.word	0xe5cb
+		.word	0xf000		@ mov pc, #0
+		.word	0xe3a0
+1:
+		adr	r1, 2b
+		teq	r1, #0
+		bne	.Langel
+		/* This is a direct-from-ROM boot.  Copy the kernel into 
+		   RAM and run it there. */
+		mov	r0, #0x30
+		mcr	p15, 0, r0, c1, c0, 0
+		mov	r0, #0x13
+		msr	cpsr, r0
+		mov	r12, #0x03000000	@ point to LEDs
+		orr	r12, r12, #0x00020000
+		orr	r12, r12, #0xba00
+		mov	r0, #0x5500
+		str	r0, [r12]
+		mov	r0, #0x10000000
+		orr	r0, r0, #0x8000
+		mov	r4, r0
+		ldr	r2, =_end
+2:
+		ldr	r3, [r1], #4
+		str	r3, [r0], #4
+		teq	r0, r2
+		bne	2b
+		mov	r0, #0xff00
+		str	r0, [r12]
+1:	
+		mov	r12, #0x03000000	@ point to LEDs
+		orr	r12, r12, #0x00020000
+		orr	r12, r12, #0xba00
+		mov	r0, #0xfe00
+		str	r0, [r12]
+
+		adr	lr, 1f
+		mov	r0, #0
+		mov	r1, #14		/* MACH_TYPE_CLPS7500 */
+		mov	pc, lr
+.Langel:
+#ifdef CONFIG_ANGELBOOT
+		/* Call Angel to switch into SVC mode. */
+		mov	r0, #0x17
+		swi	0x123456
+#endif
+		/* Ensure all interrupts are off and MMU disabled */
+		mrs	r0, cpsr
+		orr	r0, r0, #0xc0
+		msr	cpsr, r0
+
+		adr	lr, 1b
+		orr	lr, lr, #0x10000000
+		mov	r0, #0x30		@ MMU off
+		mcr	p15, 0, r0, c1, c0, 0
+		mov	r0, r0
+	 	mov	pc, lr
+
+		.ltorg
+
+1:
+/* And the rest */
+#include "head.S"
diff -u --recursive --new-file v2.4.3/linux/arch/arm/boot/compressed/head-shark.S linux/arch/arm/boot/compressed/head-shark.S
--- v2.4.3/linux/arch/arm/boot/compressed/head-shark.S	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/boot/compressed/head-shark.S	Thu Apr 12 12:03:50 2001
@@ -1,5 +1,5 @@
 /* The head-file for the Shark
- * by Alexander.Schulz@stud.uni-karlsruhe.de
+ * by Alexander Schulz <aschulz@netwinder.org>
  *
  * Does the following:
  * - get the memory layout from firmware. This can only be done as long as the mmu
@@ -20,8 +20,6 @@
 
 		b	__beginning
 	
-__serial_addr:	.long	0xf7eff3f8
-		.long	0				@ space
 __ofw_data:	.long	0				@ the number of memory blocks
 		.space  128				@ (startaddr,size) ...
 		.space  128				@ bootargs
@@ -31,14 +29,10 @@
 
 		mov	r0, #0xC0			@ disable irq and fiq
 		mov	r1, r0
-		mrs	r3, cpsr_all
+		mrs	r3, cpsr
 		bic	r2, r3, r0
 		eor	r2, r2, r1
-		msr	cpsr_all, r2
-
-		ldr	r0, __serial_addr		@ disable serial interrupt
-		mov	r1, #0				@ hangs the machine, I don t know why.
-		strb	r1, [r0, #0x01]
+		msr	cpsr_c, r2
 
 		mov	r0, r4				@ get the Memory layout from firmware
 		adr	r1, __ofw_data
diff -u --recursive --new-file v2.4.3/linux/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S
--- v2.4.3/linux/arch/arm/boot/compressed/head.S	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/boot/compressed/head.S	Thu Apr 12 12:03:50 2001
@@ -87,7 +87,8 @@
 
 		b	1f
 		.word	0x016f2818		@ Magic numbers to help the loader
-		.word	start	
+		.word	start			@ absolute load/run zImage address
+		.word	_edata			@ zImage end address
 1:		mov	r7, r1			@ save architecture ID
 		mov	r8, #0			@ save r0
 #ifdef CONFIG_ANGELBOOT
@@ -210,7 +211,7 @@
 		mov	r0, r3
 		mov	r8, r0, lsr #18
 		mov	r8, r8, lsl #18		@ start of RAM
-		add	r9, r8, #0x20000000	@ the maximum RAM size
+		add	r9, r8, #0x10000000	@ a reasonable RAM size
 		mov	r1, #0x12
 		orr	r1, r1, #3 << 10
 		add	r2, r3, #16384
diff -u --recursive --new-file v2.4.3/linux/arch/arm/boot/compressed/ll_char_wr.S linux/arch/arm/boot/compressed/ll_char_wr.S
--- v2.4.3/linux/arch/arm/boot/compressed/ll_char_wr.S	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/boot/compressed/ll_char_wr.S	Thu Apr 12 12:03:50 2001
@@ -16,7 +16,7 @@
 @ Regs: [] = corruptible
 @       {} = used
 @       () = do not use
-#define __ASSEMBLY__
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 		.text
diff -u --recursive --new-file v2.4.3/linux/arch/arm/boot/compressed/ofw-shark.c linux/arch/arm/boot/compressed/ofw-shark.c
--- v2.4.3/linux/arch/arm/boot/compressed/ofw-shark.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/boot/compressed/ofw-shark.c	Thu Apr 12 12:03:50 2001
@@ -1,7 +1,7 @@
 /*
  * linux/arch/arm/boot/compressed/ofw-shark.c
  *
- * by Alexander.Schulz@stud.uni-karlsruhe.de
+ * by Alexander Schulz <aschulz@netwinder.org>
  *
  * This file is used to get some basic information
  * about the memory layout of the shark we are running
@@ -11,6 +11,7 @@
 
 
 #include <linux/kernel.h>
+#include <linux/types.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 
@@ -18,7 +19,7 @@
 asmlinkage void
 create_params (unsigned long *buffer)
 {
-	/* Is there a better address? Also change in kernel/arch.c */
+	/* Is there a better address? Also change in mach-shark/arch.c */
 	struct param_struct *params = (struct param_struct *) 0x08003000;
 	int j,i,m,k,nr_banks,size;
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/boot/compressed/setup-sa1100.S linux/arch/arm/boot/compressed/setup-sa1100.S
--- v2.4.3/linux/arch/arm/boot/compressed/setup-sa1100.S	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/boot/compressed/setup-sa1100.S	Thu Apr 12 12:03:50 2001
@@ -24,6 +24,9 @@
 PPC_BASE:	.long	0x90060000
 #define PPAR	0x08
 
+IC_BASE:	.long	0x90050000
+#define ICMR	0x04
+
 UART1_BASE:	.long	0x80010000
 UART3_BASE:	.long	0x80050000
 #define UTCR0           0x00
@@ -52,6 +55,11 @@
 ENTRY(sa1100_setup)
 		mov	r3, r0			@ keep machine type in r3
 
+		@ Clear all interrupt sources
+		ldr	r0, IC_BASE
+		mov	r1, #0
+		str	r1, [r0, #ICMR]
+
 @ Read System Configuration "Register" for Assabet.
 @ (taken from "Intel StrongARM SA-1110 Microprocessor Development Board
 @ User's Guide," p.4-9)
@@ -87,6 +95,7 @@
 		@ Initialize UART (if bootloader has not done it yet)...
 		teq	r3, #MACH_TYPE_BRUTUS
 		teqne	r3, #MACH_TYPE_ASSABET
+		teqne	r3, #MACH_TYPE_GRAPHICSCLIENT
 		bne	skip_uart
 
 		@ UART3 if Assabet is used with Neponset
@@ -95,6 +104,11 @@
 		ldreq	r0, UART3_BASE
 		beq	uart_init
 
+		@ UART3 on GraphicsClient
+		teq	r3, #MACH_TYPE_GRAPHICSCLIENT
+		ldreq	r0, UART3_BASE
+		beq	uart_init
+
 		@ At least for Brutus, the UART1 is used through
 		@ the alternate GPIO function...
 		teq	r3, #MACH_TYPE_BRUTUS
@@ -115,7 +129,8 @@
 
 uart1:		ldr	r0, UART1_BASE
 
-uart_init:	ldr	r1, [r0, #UTSR1]
+uart_init:
+1:		ldr	r1, [r0, #UTSR1]
 		tst	r1, #1<<0		@ TBY
 		bne	1b
 		mov	r1, #0
diff -u --recursive --new-file v2.4.3/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.4.3/linux/arch/arm/config.in	Fri Feb  9 11:38:27 2001
+++ linux/arch/arm/config.in	Tue Apr 17 17:19:24 2001
@@ -9,6 +9,8 @@
 define_bool CONFIG_SBUS n
 define_bool CONFIG_MCA n
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 
 mainmenu_option next_comment
@@ -21,10 +23,8 @@
 mainmenu_option next_comment
 comment 'Loadable module support'
 bool 'Enable loadable module support' CONFIG_MODULES
-if [ "$CONFIG_MODULES" = "y" ]; then
-   bool '  Set version information on all module symbols' CONFIG_MODVERSIONS
-   bool '  Kernel module loader' CONFIG_KMOD
-fi
+dep_bool '  Set version information on all module symbols' CONFIG_MODVERSIONS $CONFIG_MODULES
+dep_bool '  Kernel module loader' CONFIG_KMOD $CONFIG_MODULES
 endmenu
 
 
@@ -36,71 +36,62 @@
 	 Cirrus-CL-PS7500FE     CONFIG_ARCH_CLPS7500 \
 	 Co-EBSA285		CONFIG_ARCH_CO285 \
 	 EBSA-110		CONFIG_ARCH_EBSA110 \
+	 LinkUp-L7200		CONFIG_ARCH_L7200 \
 	 FootBridge		CONFIG_ARCH_FOOTBRIDGE \
 	 Integrator		CONFIG_ARCH_INTEGRATOR \
 	 RiscPC			CONFIG_ARCH_RPC \
- 	 SA1100-based		CONFIG_ARCH_SA1100" RiscPC
-
-# the following are placeholders for when they are fully integrated
-#	 LinkUp-L7200		CONFIG_ARCH_L7200
+ 	 SA1100-based		CONFIG_ARCH_SA1100 \
+ 	 CLPS711x/EP721x-based	CONFIG_ARCH_CLPS711X" RiscPC
 
 mainmenu_option next_comment
 comment 'Archimedes/A5000 Implementations'
-if [ "$CONFIG_ARCH_ARCA5K" = "y" ]; then
-   # These architectures will be combined.  However, until this
-   # is complete...  Note that the ARC will take precidence over
-   # A5K
-   comment 'Archimedes/A5000 Implementations (select only ONE)'
-
-   bool '  Archimedes' CONFIG_ARCH_ARC
-   bool '  A5000' CONFIG_ARCH_A5K
-fi
+# These architectures will be combined.  However, until this
+# is complete...  Note that the ARC will take precedence over
+# A5K
+comment 'Archimedes/A5000 Implementations (select only ONE)'
+dep_bool '  Archimedes' CONFIG_ARCH_ARC $CONFIG_ARCH_ARCA5K
+dep_bool '  A5000' CONFIG_ARCH_A5K $CONFIG_ARCH_ARCA5K
 endmenu
 
 mainmenu_option next_comment
 comment 'Footbridge Implementations'
-if [ "$CONFIG_ARCH_FOOTBRIDGE" = "y" ]; then
-   bool '  CATS' CONFIG_ARCH_CATS
-   bool '  Compaq Personal Server' CONFIG_ARCH_PERSONAL_SERVER
-   bool '  EBSA285 (addin mode)' CONFIG_ARCH_EBSA285_ADDIN
-   bool '  EBSA285 (host mode)' CONFIG_ARCH_EBSA285_HOST
-   bool '  NetWinder' CONFIG_ARCH_NETWINDER
-fi
+dep_bool '  CATS' CONFIG_ARCH_CATS $CONFIG_ARCH_FOOTBRIDGE
+dep_bool '  Compaq Personal Server' CONFIG_ARCH_PERSONAL_SERVER $CONFIG_ARCH_FOOTBRIDGE
+dep_bool '  EBSA285 (addin mode)' CONFIG_ARCH_EBSA285_ADDIN $CONFIG_ARCH_FOOTBRIDGE
+dep_bool '  EBSA285 (host mode)' CONFIG_ARCH_EBSA285_HOST $CONFIG_ARCH_FOOTBRIDGE
+dep_bool '  NetWinder' CONFIG_ARCH_NETWINDER $CONFIG_ARCH_FOOTBRIDGE
 endmenu
 
 mainmenu_option next_comment
 comment 'SA11x0 Implementations'
-if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-
-   bool '  Assabet' CONFIG_SA1100_ASSABET
-   if [ "$CONFIG_SA1100_ASSABET" = "y" ]; then
-      bool '    Include support for Neponset' CONFIG_ASSABET_NEPONSET
-   fi
-   bool '  Brutus' CONFIG_SA1100_BRUTUS
-   bool '  CerfBoard' CONFIG_SA1100_CERF
-   bool '  Compaq iPAQ H3600 (Bitsy)' CONFIG_SA1100_BITSY
-#   bool '  Empeg' CONFIG_SA1100_EMPEG
-#   bool '  Itsy' CONFIG_SA1100_ITSY
-   bool '  LART' CONFIG_SA1100_LART
-#   bool '  PLEB' CONFIG_SA1100_PLEB
-   bool '  ThinClient' CONFIG_SA1100_THINCLIENT
-   bool '  GraphicsClient' CONFIG_SA1100_GRAPHICSCLIENT
-   bool '  nanoEngine' CONFIG_SA1100_NANOENGINE
-   bool '  Victor' CONFIG_SA1100_VICTOR
-#   bool '  Tifon' CONFIG_SA1100_TIFON
-   bool '  XP860' CONFIG_SA1100_XP860
-
-   # Someday, we'll support this as a general option.
-   bool '  Load kernel using Angel Debug Monitor' CONFIG_ANGELBOOT
-
-   # Determine if SA1111 support is required
-   if [ "$CONFIG_ASSABET_NEPONSET" = "y" -o \
-	"$CONFIG_SA1100_XP860" = "y" ]; then
-      define_bool CONFIG_SA1111 y
-   fi
+dep_bool '  Assabet' CONFIG_SA1100_ASSABET $CONFIG_ARCH_SA1100
+dep_bool '    Include support for Neponset' CONFIG_ASSABET_NEPONSET $CONFIG_SA1100_ASSABET
+dep_bool '  Brutus' CONFIG_SA1100_BRUTUS $CONFIG_ARCH_SA1100
+dep_bool '  CerfBoard' CONFIG_SA1100_CERF $CONFIG_ARCH_SA1100
+dep_bool '  Compaq iPAQ H3600 (Bitsy)' CONFIG_SA1100_BITSY $CONFIG_ARCH_SA1100
+#dep_bool '  Empeg' CONFIG_SA1100_EMPEG $CONFIG_ARCH_SA1100
+#dep_bool '  Itsy' CONFIG_SA1100_ITSY $CONFIG_ARCH_SA1100
+dep_bool '  LART' CONFIG_SA1100_LART $CONFIG_ARCH_SA1100
+#dep_bool '  PLEB' CONFIG_SA1100_PLEB $CONFIG_ARCH_SA1100
+dep_bool '  GraphicsClient' CONFIG_SA1100_GRAPHICSCLIENT $CONFIG_ARCH_SA1100
+dep_bool '  nanoEngine' CONFIG_SA1100_NANOENGINE $CONFIG_ARCH_SA1100
+dep_bool '  Victor' CONFIG_SA1100_VICTOR $CONFIG_ARCH_SA1100
+dep_bool '  Sherman' CONFIG_SA1100_SHERMAN $CONFIG_ARCH_SA1100
+dep_bool '  XP860' CONFIG_SA1100_XP860 $CONFIG_ARCH_SA1100
+dep_bool '  Pangolin' CONFIG_SA1100_PANGOLIN $CONFIG_ARCH_SA1100
+
+# Determine if SA1111 support is required
+if [ "$CONFIG_ASSABET_NEPONSET" = "y" -o \
+     "$CONFIG_SA1100_XP860" = "y" ]; then
+   define_bool CONFIG_SA1111 y
 fi
 endmenu
 
+mainmenu_option next_comment
+comment 'CLPS711X/EP721X Implementations'
+dep_bool '  P720T' CONFIG_ARCH_P720T $CONFIG_ARCH_CLPS711X
+endmenu
+
 # Definitions to make life easier
 if [ "$CONFIG_ARCH_ARCA5K" = "y" -o \
      "$CONFIG_ARCH_RPC" = "y" ]; then
@@ -147,49 +138,77 @@
 
 comment 'Processor Type'
 
-# Select CPU and optimisation dependent on architecture
-if [ "$CONFIG_ARCH_RPC" = "y" ]; then
+# Firstly, figure out what processor architecture version we should be using.
+if [ "$CONFIG_ARCH_RPC"        = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then
    define_bool CONFIG_CPU_32v3 y
-   bool 'Support ARM610 processor' CONFIG_CPU_ARM6
-   bool 'Support ARM710 processor' CONFIG_CPU_ARM7
-   bool 'Support StrongARM(R) SA-110 processor' CONFIG_CPU_SA110
+else
+   define_bool CONFIG_CPU_32v3 n
 fi
-if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
-     "$CONFIG_FOOTBRIDGE" = "y" -o \
-     "$CONFIG_ARCH_TBOX" = "y" -o \
-     "$CONFIG_ARCH_SHARK" = "y" -o \
-     "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then
+if [ "$CONFIG_ARCH_EBSA110"    = "y" -o "$CONFIG_FOOTBRIDGE"    = "y" -o \
+     "$CONFIG_ARCH_TBOX"       = "y" -o "$CONFIG_ARCH_SHARK"    = "y" -o \
+     "$CONFIG_ARCH_NEXUSPCI"   = "y" -o "$CONFIG_ARCH_CLPS711X" = "y" -o \
+     "$CONFIG_ARCH_INTEGRATOR" = "y" -o "$CONFIG_ARCH_SA1100"   = "y" -o \
+     "$CONFIG_ARCH_L7200"      = "y" ]; then
    define_bool CONFIG_CPU_32v4 y
-   define_bool CONFIG_CPU_SA110 y
+else
+   define_bool CONFIG_CPU_32v4 n
 fi
+
+# Select CPU types depending on the architecture selected.
+# We use this to select which CPUs are supported, and to select
+# the compiler tuning options.
+
+# ARM610
+if [ "$CONFIG_ARCH_RPC" = "y" ]; then
+   bool 'Support ARM610 processor' CONFIG_CPU_ARM610
+else
+   define_bool CONFIG_CPU_ARM610 n
+fi
+
+# ARM710
 if [ "$CONFIG_ARCH_CLPS7500" = "y" ]; then
-   define_bool CONFIG_CPU_32v3 y
-   define_bool CONFIG_CPU_ARM7 y
+   define_bool CONFIG_CPU_ARM710 y
+else
+   if [ "$CONFIG_ARCH_RPC" = "y" ]; then
+      bool 'Support ARM710 processor' CONFIG_CPU_ARM710
+   else
+      define_bool CONFIG_CPU_ARM710 n
+   fi
 fi
-if [ "$CONFIG_ARCH_L7200" = "y" ]; then
-   define_bool CONFIG_CPU_32v4 y
-   define_bool CONFIG_CPU_ARM720 y
+
+# ARM720T
+if [ "$CONFIG_ARCH_CLPS711X" = "y" -o "$CONFIG_ARCH_L7200" = "y" ]; then
+   define_bool CONFIG_CPU_ARM720T y
+else
+   if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
+      bool 'Support ARM720T processor' CONFIG_CPU_ARM720T
+   else
+      define_bool CONFIG_CPU_ARM720T n
+   fi
 fi
+
+# ARM920T
 if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-   define_bool CONFIG_CPU_32v4 y
-   bool 'Support ARM720 processor' CONFIG_CPU_ARM720
-   bool 'Support ARM920 processor' CONFIG_CPU_ARM920
-#   bool 'Support ARM10 processor' CONFIG_CPU_ARM10
-fi
-if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-   define_bool CONFIG_CPU_32v4 y
-   define_bool CONFIG_CPU_SA1100 y
+   bool 'Support ARM920T processor' CONFIG_CPU_ARM920T
+else
+   define_bool CONFIG_CPU_ARM920T n
 fi
-
-if [ "$CONFIG_CPU_ARM920" = "y" ]; then
-   bool '  ARM920 CPU idle' CONFIG_CPU_ARM920_CPU_IDLE
-   bool '  ARM920 I-Cache on' CONFIG_CPU_ARM920_I_CACHE_ON
-   bool '  ARM920 D-Cache on' CONFIG_CPU_ARM920_D_CACHE_ON
+if [ "$CONFIG_CPU_ARM920T" = "y" ]; then
+   bool '  ARM920T CPU idle' CONFIG_CPU_ARM920_CPU_IDLE
+   bool '  ARM920T I-Cache on' CONFIG_CPU_ARM920_I_CACHE_ON
+   bool '  ARM920T D-Cache on' CONFIG_CPU_ARM920_D_CACHE_ON
    if [ "$CONFIG_CPU_ARM920_D_CACHE_ON" = "y" ] ; then
-      bool '  Force write through caches on ARM920' CONFIG_CPU_ARM920_WRITETHROUGH
+      bool '  Force write through caches on ARM920T' CONFIG_CPU_ARM920_WRITETHROUGH
    fi
 fi
-#if [ "$CONFIG_CPU_ARM10" = "y" ]; then
+
+# ARM1020
+#if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
+#   bool 'Support ARM1020 processor' CONFIG_CPU_ARM1020
+#else
+    define_bool CONFIG_CPU_ARM1020 n
+#fi
+#if [ "$CONFIG_CPU_ARM1020" = "y" ]; then
 #   bool '  ARM10 I-Cache on' CONFIG_CPU_ARM10_I_CACHE_ON
 #   bool '  ARM10 D-Cache on' CONFIG_CPU_ARM10_D_CACHE_ON
 #   if [ "$CONFIG_CPU_ARM10_D_CACHE_ON" = "y" ] ; then
@@ -197,6 +216,30 @@
 #   fi
 #fi
 
+# SA110
+if [ "$CONFIG_ARCH_EBSA110"  = "y" -o "$CONFIG_FOOTBRIDGE" = "y" -o \
+     "$CONFIG_ARCH_TBOX"     = "y" -o "$CONFIG_ARCH_SHARK" = "y" -o \
+     "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then
+   define_bool CONFIG_CPU_SA110 y
+else
+   if [ "$CONFIG_ARCH_RPC" = "y" ]; then
+      bool 'Support StrongARM(R) SA-110 processor' CONFIG_CPU_SA110
+   else
+      define_bool CONFIG_CPU_SA110 n
+   fi
+fi
+
+# SA1100
+if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
+   define_bool CONFIG_CPU_SA1100 y
+else
+   define_bool CONFIG_CPU_SA1100 n
+fi
+
+#if [ "$CONFIG_CPU_32" = "y" ]; then
+#   bool 'Support Thumb instructions' CONFIG_ARM_THUMB
+#fi
+
 # Select various configuration options depending on the machine type
 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
    define_bool CONFIG_DISCONTIGMEM y
@@ -209,8 +252,12 @@
 mainmenu_option next_comment
 comment 'General setup'
 
+comment 'Please ensure that you have read the help on the next option'
+bool 'Load kernel using Angel Debug Monitor' CONFIG_ANGELBOOT
+
 # Now handle the bus types
-if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \
+if [ "$CONFIG_ARCH_FTVPCI" = "y" -o \
+     "$CONFIG_ARCH_SHARK" = "y" -o \
      "$CONFIG_FOOTBRIDGE_HOST" = "y" ]; then
    define_bool CONFIG_PCI y
 else
@@ -223,21 +270,19 @@
 fi
 
 if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
-     "$CONFIG_ARCH_SHARK" = "y" ]; then
+     "$CONFIG_ARCH_SHARK" = "y" -o \
+     "$CONFIG_ARCH_CLPS7500" = "y" -o \
+     "$CONFIG_ARCH_EBSA110" = "y" ]; then
    define_bool CONFIG_ISA y
-   define_bool CONFIG_ISA_DMA y
 else
    define_bool CONFIG_ISA n
-   define_bool CONFIG_ISA_DMA n
 fi
 
-# Do we have a PC-type keyboard in this architecture?
-if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" ]; then
-   define_bool CONFIG_PC_KEYB y
-   define_bool CONFIG_PC_KEYMAP y
-fi
-if [ "$CONFIG_SA1100_ASSABET" = "y" ]; then
-   define_bool CONFIG_PC_KEYMAP y
+if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
+     "$CONFIG_ARCH_SHARK" = "y" ]; then
+   define_bool CONFIG_ISA_DMA y
+else
+   define_bool CONFIG_ISA_DMA n
 fi
 
 source drivers/pci/Config.in
@@ -251,42 +296,44 @@
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
-tristate 'NWFPE math emulation' CONFIG_NWFPE
+tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE
+dep_tristate 'FastFPE math emulation (experimental)' CONFIG_FPE_FASTFPE $CONFIG_EXPERIMENTAL
 choice 'Kernel core (/proc/kcore) format' \
 	"ELF		CONFIG_KCORE_ELF	\
 	 A.OUT		CONFIG_KCORE_AOUT" ELF
 tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL
+dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32
 
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   bool 'Power Management support' CONFIG_PM
-fi
-
-if [ "$CONFIG_CPU_32" = "y" ]; then
-   tristate 'RISC OS personality' CONFIG_ARTHUR
-fi
-if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
-     "$CONFIG_ARCH_SA1100" = "y" -o \
-     "$CONFIG_ARCH_CLPS7500" = "y" -o \
+if [ "$CONFIG_ARCH_EBSA110" = "y" -o         \
+     "$CONFIG_ARCH_SA1100" = "y" -o          \
+     "$CONFIG_ARCH_CLPS7500" = "y" -o        \
      "$CONFIG_ARCH_PERSONAL_SERVER" = "y" -o \
-     "$CONFIG_ARCH_CATS" = "y" -o \
-     "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
+     "$CONFIG_ARCH_CATS" = "y" -o            \
+     "$CONFIG_ARCH_INTEGRATOR" = "y" -o      \
+     "$CONFIG_ARCH_P720T" = "y" ]; then
    string 'Default kernel command string' CONFIG_CMDLINE ""
 fi
-if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
-     "$CONFIG_ARCH_EBSA110" = "y" -o   \
-     "$CONFIG_ARCH_EBSA285" = "y" -o   \
-     "$CONFIG_ARCH_CO285" = "y" -o     \
-     "$CONFIG_ARCH_SA1100" = "y" -o    \
-     "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
+if [ "$CONFIG_ARCH_NETWINDER" = "y" -o  \
+     "$CONFIG_ARCH_EBSA110" = "y" -o    \
+     "$CONFIG_ARCH_EBSA285" = "y" -o    \
+     "$CONFIG_ARCH_FTVPCI" = "y" -o     \
+     "$CONFIG_ARCH_SHARK" = "y" -o      \
+     "$CONFIG_ARCH_CO285" = "y" -o      \
+     "$CONFIG_ARCH_SA1100" = "y" -o     \
+     "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
+     "$CONFIG_ARCH_P720T" = "y" ]; then
    bool 'Timer and CPU usage LEDs' CONFIG_LEDS
    if [ "$CONFIG_LEDS" = "y" ]; then
-      if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
-	   "$CONFIG_ARCH_EBSA285" = "y" -o   \
-	   "$CONFIG_ARCH_CO285" = "y" -o     \
-	   "$CONFIG_ARCH_SA1100" = "y" -o    \
-           "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
+      if [ "$CONFIG_ARCH_NETWINDER" = "y" -o  \
+	   "$CONFIG_ARCH_EBSA285" = "y" -o    \
+	   "$CONFIG_ARCH_SHARK" = "y" -o      \
+	   "$CONFIG_ARCH_CO285" = "y" -o      \
+	   "$CONFIG_ARCH_SA1100" = "y" -o     \
+           "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
+	   "$CONFIG_ARCH_P720T" = "y" ]; then
          bool '  Timer LED' CONFIG_LEDS_TIMER
          bool '  CPU usage LED' CONFIG_LEDS_CPU
       fi
@@ -350,9 +397,13 @@
 fi
 endmenu
 
+if [ "$CONFIG_ARCH_CLPS711X" = "y" ]; then
+   source drivers/ssi/Config.in
+fi
+
 source drivers/ieee1394/Config.in
 
-source drivers/i2o/Config.in
+source drivers/message/i2o/Config.in
 
 mainmenu_option next_comment
 comment 'ISDN subsystem'
@@ -363,6 +414,11 @@
 fi
 endmenu
 
+#
+# input before char - char/joystick depends on it. As does USB.
+#
+source drivers/input/Config.in
+
 source drivers/char/Config.in
 if [ "$CONFIG_ARCH_ACORN" = "y" -a \
      "$CONFIG_BUSMOUSE" = "y" ]; then
@@ -373,11 +429,34 @@
    fi
 fi
 
+source drivers/media/Config.in
+
 source fs/Config.in
 
 if [ "$CONFIG_VT" = "y" ]; then
    mainmenu_option next_comment
    comment 'Console drivers'
+   # Select the keyboard type for this architecture.
+   if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
+        "$CONFIG_ARCH_CLPS7500" = "y" -o   \
+        "$CONFIG_ARCH_SHARK" = "y" ]; then
+      define_bool CONFIG_PC_KEYB y
+   fi
+   if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
+      define_bool CONFIG_KMI_KEYB y
+      define_bool CONFIG_KMI_MOUSE y
+   fi
+
+   # Do we use the PC-type keyboard map?
+   if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
+        "$CONFIG_ARCH_SHARK" = "y" -o      \
+        "$CONFIG_ARCH_SA1100" = "y" -o     \
+        "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
+        "$CONFIG_ARCH_TBOX" = "y" -o       \
+        "$CONFIG_ARCH_CLPS7500" = "y" -o   \
+        "$CONFIG_ARCH_P720T" = "y" ]; then
+      define_bool CONFIG_PC_KEYMAP y
+   fi
    if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then
       bool 'VGA text console' CONFIG_VGA_CONSOLE
    fi
@@ -388,6 +467,7 @@
 
 if [ "$CONFIG_ARCH_ACORN" = "y" -o \
      "$CONFIG_ARCH_CLPS7500" = "y" -o \
+     "$CONFIG_ARCH_TBOX" = "y" -o \
      "$CONFIG_ARCH_SHARK" = "y" -o \
      "$CONFIG_PCI" = "y" ]; then
    mainmenu_option next_comment
@@ -408,23 +488,14 @@
 
 # Always compile kernel with framepointer (until 2.4 real comes out)
 # Bug reports aren't much use without this.
-#bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER
-define_bool CONFIG_FRAME_POINTER y
+bool 'Compile kernel without frame pointer' CONFIG_NO_FRAME_POINTER
 bool 'Verbose kernel error messages' CONFIG_DEBUG_ERRORS
 bool 'Verbose user fault messages' CONFIG_DEBUG_USER
 bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
-if [ "$CONFIG_CPU_26" = "y" ]; then
-   bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE
-fi
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   # These options are only for real kernel hackers
-   # who want to get their hands dirty. 
-   bool 'Kernel low-level debugging functions' CONFIG_DEBUG_LL
-   if [ "$CONFIG_DEBUG_LL" = "y" ]; then
-      if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
-         bool 'Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT
-      fi
-   fi
-fi
+dep_bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE $CONFIG_CPU_26
+# These options are only for real kernel hackers who want to get their hands dirty. 
+dep_bool 'Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_EXPERIMENTAL
+dep_bool '  Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
+dep_bool '  kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
 endmenu
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile
--- v2.4.3/linux/arch/arm/kernel/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/kernel/Makefile	Thu Apr 12 12:20:31 2001
@@ -13,16 +13,18 @@
 AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR)
 AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR)
 
+# This is depreciated.
 O_OBJS_arc        = dma-arc.o oldlatches.o
 O_OBJS_rpc        = dma-rpc.o
 O_OBJS_footbridge = dma-footbridge.o isa.o
 O_OBJS_l7200      = fiq.o
 
-pci-nexuspci	  = plx90x0.o
+pci-ftvpci	  = plx90x0.o
 pci-footbridge	  = dec21285.o
 pci-shark	  = via82c505.o
 
-pci-$(CONFIG_ARCH_NEXUSPCI) += ftv-pci.o
+# this is here to allow us to eventually move it out to mach-ftvpci
+pci-$(CONFIG_ARCH_FTVPCI) += ftv-pci.o
 
 
 O_TARGET := kernel.o
@@ -36,7 +38,7 @@
 obj-n		:=
 obj-		:=
 
-export-objs	:= armksyms.o dma.o ecard.o fiq.o oldlatches.o time.o
+export-objs	:= armksyms.o dma.o ecard.o fiq.o io.o oldlatches.o time.o
 
 no-irq-arch	:= $(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) \
 		   $(CONFIG_ARCH_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110)
@@ -46,16 +48,21 @@
 endif
 
 obj-$(CONFIG_ARCH_ACORN) += ecard.o fiq.o time-acorn.o
+obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o
 obj-$(CONFIG_DEBUG_LL)	+= debug-$(PROCESSOR).o
 obj-$(CONFIG_MODULES)	+= armksyms.o
 obj-$(CONFIG_ARTHUR)	+= arthur.o
 obj-$(CONFIG_ISA_DMA)	+= dma-isa.o
 obj-$(CONFIG_PCI)	+= bios32.o $(pci-$(MACHINE)) $(pci-y)
 
+ifneq ($(MACHINE),ebsa110)
+  obj-y		+= io.o
+endif
+
 all: kernel.o $(HEAD_OBJ) init_task.o
 
 include $(TOPDIR)/Rules.make
 
 # Spell out some dependencies that `make dep' doesn't spot
-entry-armv.o: calls.S ../lib/constants.h
-entry-armo.o: calls.S ../lib/constants.h
+entry-armv.o: calls.S $(TOPDIR)/include/asm-arm/constants.h
+entry-armo.o: calls.S $(TOPDIR)/include/asm-arm/constants.h
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/arch.c linux/arch/arm/kernel/arch.c
--- v2.4.3/linux/arch/arm/kernel/arch.c	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/arch.c	Thu Apr 12 12:20:31 2001
@@ -19,10 +19,9 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/dec21285.h>
 
-unsigned int vram_size;
+extern void genarch_init_irq(void);
 
-extern void setup_initrd(unsigned int start, unsigned int size);
-extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz);
+unsigned int vram_size;
 
 #ifdef CONFIG_ARCH_ACORN
 
@@ -79,6 +78,7 @@
 	DISABLE_PARPORT(1)
 	FIXUP(fixup_acorn)
 	MAPIO(rpc_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_ARC
@@ -86,6 +86,7 @@
 	MAINTAINER("Dave Gilbert")
 	BOOT_PARAMS(0x0207c000)
 	FIXUP(fixup_acorn)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_A5K
@@ -93,11 +94,13 @@
 	MAINTAINER("Russell King")
 	BOOT_PARAMS(0x0207c000)
 	FIXUP(fixup_acorn)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #endif
 
 #ifdef CONFIG_ARCH_L7200
+extern void __init l7200_map_io(void);
 
 static void __init
 fixup_l7200(struct machine_desc *desc, struct param_struct *params,
@@ -109,34 +112,28 @@
         mi->bank[0].node  = 0;
 
         ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-        setup_ramdisk( 1, 0, 0, 8192 );
-        setup_initrd( __phys_to_virt(0xf1000000), 0x00162b0d);
-}
+        setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE);
+        setup_initrd( __phys_to_virt(0xf1000000), 0x005dac7b);
 
-extern void __init l7200_map_io(void);
+        /* Serial Console COM2 and LCD */
+	strcpy( *cmdline, "console=tty0 console=ttyLU1,115200");
+
+        /* Serial Console COM1 and LCD */
+	//strcpy( *cmdline, "console=tty0 console=ttyLU0,115200");
+
+        /* Console on LCD */
+	//strcpy( *cmdline, "console=tty0");
+}
 
-MACHINE_START(L7200, "LinkUp Systems L7200SDB")
-	MAINTAINER("Steve Hill")
+MACHINE_START(L7200, "LinkUp Systems L7200")
+	MAINTAINER("Steve Hill / Scott McConnell")
 	BOOT_MEM(0xf0000000, 0x80040000, 0xd0000000)
 	FIXUP(fixup_l7200)
 	MAPIO(l7200_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 
-#ifdef CONFIG_ARCH_EBSA110
-
-extern void __init ebsa110_map_io(void);
-
-MACHINE_START(EBSA110, "EBSA110")
-	MAINTAINER("Russell King")
-	BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000)
-	BOOT_PARAMS(0x00000400)
-	DISABLE_PARPORT(0)
-	DISABLE_PARPORT(2)
-	SOFT_REBOOT
-	MAPIO(ebsa110_map_io)
-MACHINE_END
-#endif
 #ifdef CONFIG_ARCH_NEXUSPCI
 
 extern void __init nexuspci_map_io(void);
@@ -145,6 +142,7 @@
 	MAINTAINER("Philip Blundell")
 	BOOT_MEM(0x40000000, 0x10000000, 0xe0000000)
 	MAPIO(nexuspci_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_TBOX
@@ -155,21 +153,25 @@
 	MAINTAINER("Philip Blundell")
 	BOOT_MEM(0x80000000, 0x00400000, 0xe0000000)
 	MAPIO(tbox_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_CLPS7110
 MACHINE_START(CLPS7110, "CL-PS7110")
 	MAINTAINER("Werner Almesberger")
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_ETOILE
 MACHINE_START(ETOILE, "Etoile")
 	MAINTAINER("Alex de Vries")
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_LACIE_NAS
 MACHINE_START(LACIE_NAS, "LaCie_NAS")
 	MAINTAINER("Benjamin Herrenschmidt")
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_CLPS7500
@@ -180,5 +182,6 @@
 	MAINTAINER("Philip Blundell")
 	BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
 	MAPIO(clps7500_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c
--- v2.4.3/linux/arch/arm/kernel/armksyms.c	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/armksyms.c	Thu Apr 12 12:20:31 2001
@@ -48,7 +48,6 @@
 extern int sys_read(int, char *, int);
 extern int sys_lseek(int, off_t, int);
 extern int sys_exit(int);
-extern int sys_wait4(int, int *, int, struct rusage *);
 
 /*
  * libgcc functions - functions that are used internally by the
@@ -77,15 +76,18 @@
 extern void fpundefinstr(void);
 extern void fp_enter(void);
 
-#define EXPORT_SYMBOL_ALIAS(sym,orig) \
- const char __kstrtab_##sym##[] __attribute__((section(".kstrtab"))) = \
-    __MODULE_STRING(##sym##); \
- const struct module_symbol __ksymtab_##sym __attribute__((section("__ksymtab"))) = \
+#define EXPORT_SYMBOL_ALIAS(sym,orig)		\
+ const char __kstrtab_##sym##[]			\
+  __attribute__((section(".kstrtab"))) =	\
+    __MODULE_STRING(sym);			\
+ const struct module_symbol __ksymtab_##sym	\
+  __attribute__((section("__ksymtab"))) =	\
     { (unsigned long)&##orig, __kstrtab_##sym };
-	/*
-	 * floating point math emulator support.
-	 * These symbols will never change their calling convention...
-	 */
+
+/*
+ * floating point math emulator support.
+ * These symbols will never change their calling convention...
+ */
 EXPORT_SYMBOL_ALIAS(kern_fp_enter,fp_enter);
 EXPORT_SYMBOL_ALIAS(fp_printk,printk);
 EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig);
@@ -95,7 +97,9 @@
 EXPORT_SYMBOL(ret_from_exception);
 #endif
 
+#ifdef CONFIG_VT
 EXPORT_SYMBOL(kd_mksound);
+#endif
 
 	/* platform dependent support */
 EXPORT_SYMBOL(dump_thread);
@@ -150,8 +154,6 @@
 #ifndef CONFIG_NO_PGT_CACHE
 EXPORT_SYMBOL(quicklists);
 #endif
-EXPORT_SYMBOL(__handle_bad_pmd);
-EXPORT_SYMBOL(__handle_bad_pmd_kernel);
 
 	/* string / mem functions */
 EXPORT_SYMBOL_NOVERS(strcpy);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/arthur.c linux/arch/arm/kernel/arthur.c
--- v2.4.3/linux/arch/arm/kernel/arthur.c	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/arthur.c	Thu Apr 12 12:20:31 2001
@@ -1,7 +1,9 @@
 /*
- * Arthur personality
+ *  linux/arch/arm/kernel/arthur.c
+ *
+ *  Copyright (C) 1998, 1999, 2000 Philip Blundell
  *
- * Copyright (C) 1998, 1999, 2000 Philip Blundell
+ * Arthur personality
  */
 
 /*
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c
--- v2.4.3/linux/arch/arm/kernel/bios32.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/kernel/bios32.c	Thu Apr 12 12:20:31 2001
@@ -307,7 +307,8 @@
 		 * parity line correctly.
 		 */
 		if (dev->vendor == PCI_VENDOR_ID_INTERG &&
-		    dev->device == PCI_DEVICE_ID_INTERG_2000)
+		    (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
+		     dev->device == PCI_DEVICE_ID_INTERG_2010))
 			busdata->features &= ~(PCI_COMMAND_SERR |
 					       PCI_COMMAND_PARITY);
 
@@ -394,6 +395,7 @@
 extern struct hw_pci netwinder_pci;
 extern struct hw_pci personal_server_pci;
 extern struct hw_pci ftv_pci;
+extern struct hw_pci shark_pci;
 extern struct hw_pci integrator_pci;
 
 void __init pcibios_init(void)
@@ -409,6 +411,12 @@
 			break;
 		}
 #endif
+#ifdef CONFIG_ARCH_SHARK
+		if (machine_is_shark()) {
+			hw_pci = &shark_pci;
+			break;
+		}
+#endif
 #ifdef CONFIG_ARCH_CATS
 		if (machine_is_cats()) {
 			hw_pci = &cats_pci;
@@ -427,8 +435,8 @@
 			break;
 		}
 #endif
-#ifdef CONFIG_ARCH_NEXUSPCI
-		if (machine_is_nexuspci()) {
+#ifdef CONFIG_ARCH_FTVPCI
+		if (machine_is_ftvpci()) {
 			hw_pci = &ftv_pci;
 			break;
 		}
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/debug-armv.S linux/arch/arm/kernel/debug-armv.S
--- v2.4.3/linux/arch/arm/kernel/debug-armv.S	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/debug-armv.S	Thu Apr 12 12:20:31 2001
@@ -12,7 +12,6 @@
 #include <linux/config.h>
 #include <linux/linkage.h>
 #include <asm/hardware.h>
-#include <asm/hardware/dec21285.h>
 
 		.text
 
@@ -67,8 +66,31 @@
 		tst	\rd, #0x10
 		beq	1001b
 		.endm
+ 	
+#elif defined(CONFIG_ARCH_SHARK)
+		.macro	addruart,rx
+		mov	\rx, #0xe0000000
+		orr	\rx, \rx, #0x000003f8
+		.endm
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx]
+		.endm
+
+		.macro	busyuart,rd,rx
+		mov	\rd, #0
+1001:		add	\rd, \rd, #1
+		teq	\rd, #0x10000
+		bne	1001b
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
 
 #elif defined(CONFIG_FOOTBRIDGE)
+
+#include <asm/hardware/dec21285.h>
+
 #ifndef CONFIG_DEBUG_DC21285_PORT
 	/* For NetWinder debugging */
 		.macro	addruart,rx
@@ -120,9 +142,12 @@
 		.macro	waituart,rd,rx
 		.endm
 #endif
-#elif defined(CONFIG_ARCH_NEXUSPCI)
+#elif defined(CONFIG_ARCH_FTVPCI)
 		.macro	addruart,rx
-		ldr	\rx, =0xfff00000
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		movne	\rx, #0xe0000000
+		moveq	\rx, #0x10000000
 		.endm
 
 		.macro	senduart,rd,rx
@@ -131,8 +156,8 @@
 
 		.macro	busyuart,rd,rx
 1001:		ldr	\rd, [\rx, #0x4]
-		tst	\rd, #1 << 0
-		bne	1001b
+		tst	\rd, #1 << 2
+		beq	1001b
 		.endm
 
 		.macro	waituart,rd,rx
@@ -164,6 +189,26 @@
 		bne	1001b
 		.endm
 
+#elif defined(CONFIG_ARCH_CLPS7500)
+		.macro	addruart,rx
+		mov	\rx, #0xe0000000
+		orr	\rx, \rx, #0x00010000
+		orr	\rx, \rx, #0x00000be0
+		.endm
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx]
+		.endm
+
+		.macro	busyuart,rd,rx
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldrb	\rd, [\rx, #0x14]
+		tst	\rd, #0x20
+		beq	1001b
+		.endm
+
 #elif defined(CONFIG_ARCH_L7200)
 
 		.equ	io_virt, IO_BASE
@@ -174,12 +219,12 @@
 		tst	\rx, #1			@ MMU enabled?
 		moveq	\rx, #io_phys		@ physical base address
 		movne	\rx, #io_virt		@ virtual address
-		add	\rx, \rx, #0x00044000	@ Ser1
-@		add	\rx, \rx, #0x00045000	@ Ser2
+		add	\rx, \rx, #0x00044000	@ UART1
+@		add	\rx, \rx, #0x00045000	@ UART2
 		.endm
 
 		.macro	senduart,rd,rx
-		str	\rd, [\rx, #0x0]	@ UARTDR1
+		str	\rd, [\rx, #0x0]	@ UARTDR
 		.endm
 
 		.macro	waituart,rd,rx
@@ -198,9 +243,6 @@
 
 #include <asm/hardware/serial_amba.h>
 
-		.equ	io_virt, 0xf0000000 + (0x16000000 >> 4)
-		.equ	io_phys, 0x16000000
-
 		.macro	addruart,rx
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
@@ -223,6 +265,41 @@
 1001:		ldr	\rd, [\rx, #0x18]	@ UARTFLG
 		tst	\rd, #1 << 3		@ UARTFLGUBUSY - 1 when busy
 		bne	1001b
+		.endm
+
+#elif defined(CONFIG_ARCH_CLPS711X)
+
+#include <asm/hardware/clps7111.h>
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #CLPS7111_PHYS_BASE
+		movne	\rx, #CLPS7111_VIRT_BASE
+#ifndef CONFIG_DEBUG_CLPS711X_UART2
+		add	\rx, \rx, #0x0000	@ UART1
+#else
+		add	\rx, \rx, #0x1000	@ UART2
+#endif
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0x0480]	@ UARTDR
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldr	\rd, [\rx, #0x0140]	@ SYSFLGx
+		tst	\rd, #1 << 11		@ UBUSYx
+		bne	1001b
+		.endm
+
+		.macro	busyuart,rd,rx
+		tst	\rx, #0x1000		@ UART2 does not have CTS here
+		bne	1002f
+1001:		ldr	\rd, [\rx, #0x0140]	@ SYSFLGx
+		tst	\rd, #1 << 8		@ CTS
+		bne	1001b
+1002:
 		.endm
 
 #else
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c
--- v2.4.3/linux/arch/arm/kernel/ecard.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/arm/kernel/ecard.c	Thu Apr 12 12:20:31 2001
@@ -37,6 +37,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/notifier.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
@@ -46,6 +47,7 @@
 #include <asm/irq.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
+#include <asm/mach/irq.h>
 
 #ifndef CONFIG_ARCH_RPC
 #define HAVE_EXPMASK
@@ -53,7 +55,7 @@
 
 enum req {
 	req_readbytes,
-	req_reset
+	req_reset_all
 };
 
 struct ecard_request {
@@ -134,19 +136,14 @@
 #define POD_INT_ADDR(x)	((volatile unsigned char *)\
 			 ((BUS_ADDR((x)) - IO_BASE) + IO_START))
 
-static void
-ecard_task_reset(struct ecard_request *req)
+static inline void ecard_task_reset(void)
 {
-	if (req->ec == NULL) {
-		ecard_t *ec;
+	ecard_t *ec;
 
-		for (ec = cards; ec; ec = ec->next)
-			if (ec->loader)
-				ecard_loader_reset(POD_INT_ADDR(ec->podaddr),
-						   ec->loader);
-	} else if (req->ec->loader)
-		ecard_loader_reset(POD_INT_ADDR(req->ec->podaddr),
-				   req->ec->loader);
+	for (ec = cards; ec; ec = ec->next)
+		if (ec->loader)
+			ecard_loader_reset(POD_INT_ADDR(ec->podaddr),
+					   ec->loader);
 }
 
 static void
@@ -156,48 +153,47 @@
 	volatile unsigned char *base_addr =
 		(volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr);
 	unsigned int len = req->length;
+	unsigned int off = req->address;
 
 	if (req->ec->slot_no == 8) {
 		/*
-		 * The card maintains an index which
-		 * increments the address into a 4096-byte
-		 * page on each access.  We need to keep
+		 * The card maintains an index which increments the address
+		 * into a 4096-byte page on each access.  We need to keep
 		 * track of the counter.
 		 */
 		static unsigned int index;
-		unsigned int offset, page;
-		unsigned char byte = 0; /* keep gcc quiet */
-
-		offset = req->address & 4095;
-		page   = req->address >> 12;
+		unsigned int page;
 
-		if (page > 256)
+		page = (off >> 12) * 4;
+		if (page > 256 * 4)
 			return;
 
-		page *= 4;
+		off &= 4095;
 
-		if (offset == 0 || index > offset) {
-			/*
-			 * We need to reset the index counter.
-			 */
+		/*
+		 * If we are reading offset 0, or our current index is
+		 * greater than the offset, reset the hardware index counter.
+		 */
+		if (off == 0 || index > off) {
 			*base_addr = 0;
 			index = 0;
 		}
 
-		while (index <= offset) {
+		/*
+		 * Increment the hardware index counter until we get to the
+		 * required offset.  The read bytes are discarded.
+		 */
+		while (index < off) {
+			unsigned char byte;
 			byte = base_addr[page];
 			index += 1;
 		}
 
 		while (len--) {
-			*buf++ = byte;
-			if (len) {
-				byte = base_addr[page];
-				index += 1;
-			}
+			*buf++ = base_addr[page];
+			index += 1;
 		}
 	} else {
-		unsigned int off = req->address;
 
 		if (!req->use_loader || !req->ec->loader) {
 			off *= 4;
@@ -220,50 +216,30 @@
 
 }
 
+static void ecard_do_request(struct ecard_request *req)
+{
+	switch (req->req) {
+	case req_readbytes:
+		ecard_task_readbytes(req);
+		break;
+
+	case req_reset_all:
+		ecard_task_reset();
+		break;
+	}
+}
+
 #ifdef CONFIG_CPU_32
 static pid_t ecard_pid;
 static wait_queue_head_t ecard_wait;
-static wait_queue_head_t ecard_done;
 static struct ecard_request *ecard_req;
 
-/* to be removed when exec_mmap becomes extern */
-static int exec_mmap(void)
-{
-	struct mm_struct * mm, * old_mm;
-
-	old_mm = current->mm;
-	if (old_mm && atomic_read(&old_mm->mm_users) == 1) {
-		flush_cache_mm(old_mm);
-		mm_release();
-		exit_mmap(old_mm);
-		flush_tlb_mm(old_mm);
-		return 0;
-	}
-
-	mm = mm_alloc();
-	if (mm) {
-		struct mm_struct *active_mm = current->active_mm;
-
-		current->mm = mm;
-		current->active_mm = mm;
-		activate_mm(active_mm, mm);
-		mm_release();
-		if (old_mm) {
-			if (active_mm != old_mm) BUG();
-			mmput(old_mm);
-			return 0;
-		}
-		mmdrop(active_mm);
-		return 0;
-	}
-	return -ENOMEM;
-}
+static DECLARE_MUTEX_LOCKED(ecard_done_sem);
 
 /*
- * Set up the expansion card
- * daemon's environment.
+ * Set up the expansion card daemon's page tables.
  */
-static void ecard_init_task(int force)
+static void ecard_init_pgtables(struct mm_struct *mm)
 {
 	/* We want to set up the page tables for the following mapping:
 	 *  Virtual	Physical
@@ -279,29 +255,41 @@
 	pgd_t *src_pgd, *dst_pgd;
 	unsigned int dst_addr = IO_START;
 
-	if (!force)
-		exec_mmap();
-
-	src_pgd = pgd_offset(current->mm, IO_BASE);
-	dst_pgd = pgd_offset(current->mm, dst_addr);
+	src_pgd = pgd_offset(mm, IO_BASE);
+	dst_pgd = pgd_offset(mm, dst_addr);
 
 	while (dst_addr < IO_START + IO_SIZE) {
 		*dst_pgd++ = *src_pgd++;
 		dst_addr += PGDIR_SIZE;
 	}
 
-	flush_tlb_range(current->mm, IO_START, IO_START + IO_SIZE);
-
 	dst_addr = EASI_START;
-	src_pgd = pgd_offset(current->mm, EASI_BASE);
-	dst_pgd = pgd_offset(current->mm, dst_addr);
+	src_pgd = pgd_offset(mm, EASI_BASE);
+	dst_pgd = pgd_offset(mm, dst_addr);
 
 	while (dst_addr < EASI_START + EASI_SIZE) {
 		*dst_pgd++ = *src_pgd++;
 		dst_addr += PGDIR_SIZE;
 	}
 
-	flush_tlb_range(current->mm, EASI_START, EASI_START + EASI_SIZE);
+	flush_tlb_range(mm, IO_START, IO_START + IO_SIZE);
+	flush_tlb_range(mm, EASI_START, EASI_START + EASI_SIZE);
+}
+
+static int ecard_init_mm(void)
+{
+	struct mm_struct * mm = mm_alloc();
+	struct mm_struct *active_mm = current->active_mm;
+
+	if (!mm)
+		return -ENOMEM;
+
+	current->mm = mm;
+	current->active_mm = mm;
+	activate_mm(active_mm, mm);
+	mmdrop(active_mm);
+	ecard_init_pgtables(mm);
+	return 0;
 }
 
 static int
@@ -309,22 +297,23 @@
 {
 	struct task_struct *tsk = current;
 
-	tsk->session = 1;
-	tsk->pgrp = 1;
-
 	/*
 	 * We don't want /any/ signals, not even SIGKILL
 	 */
 	sigfillset(&tsk->blocked);
 	sigemptyset(&tsk->pending.signal);
 	recalc_sigpending(tsk);
-
 	strcpy(tsk->comm, "kecardd");
+	daemonize();
 
 	/*
-	 * Set up the environment
+	 * Allocate a mm.  We're not a lazy-TLB kernel task since we need
+	 * to set page table entries where the user space would be.  Note
+	 * that this also creates the page tables.  Failure is not an
+	 * option here.
 	 */
-	ecard_init_task(0);
+	if (ecard_init_mm())
+		panic("kecardd: unable to alloc mm\n");
 
 	while (1) {
 		struct ecard_request *req;
@@ -338,16 +327,8 @@
 			}
 		} while (req == NULL);
 
-		switch (req->req) {
-		case req_readbytes:
-			ecard_task_readbytes(req);
-			break;
-
-		case req_reset:
-			ecard_task_reset(req);
-			break;
-		}
-		wake_up(&ecard_done);
+		ecard_do_request(req);
+		up(&ecard_done_sem);
 	}
 }
 
@@ -357,76 +338,90 @@
  * FIXME: The test here is not sufficient to detect if the
  * kcardd is running.
  */
-static inline void
+static void
 ecard_call(struct ecard_request *req)
 {
 	/*
-	 * If we're called from task 0, or from an
-	 * interrupt (will be keyboard interrupt),
-	 * we forcefully set up the memory map, and
-	 * call the loader.  We can't schedule, or
-	 * sleep for this call.
+	 * Make sure we have a context that is able to sleep.
 	 */
-	if ((current == &init_task || in_interrupt()) &&
-	    req->req == req_reset && req->ec == NULL) {
-		ecard_init_task(1);
-		ecard_task_reset(req);
-	} else {
-		if (ecard_pid <= 0)
-			ecard_pid = kernel_thread(ecard_task, NULL,
-					CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+	if (current == &init_task || in_interrupt())
+		BUG();
 
-		ecard_req = req;
+	if (ecard_pid <= 0)
+		ecard_pid = kernel_thread(ecard_task, NULL,
+				CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 
-		wake_up(&ecard_wait);
+	ecard_req = req;
+	wake_up(&ecard_wait);
 
-		sleep_on(&ecard_done);
-	}
+	/*
+	 * Now wait for kecardd to run.
+	 */
+	down(&ecard_done_sem);
 }
 #else
 /*
  * On 26-bit processors, we don't need the kcardd thread to access the
  * expansion card loaders.  We do it directly.
  */
-static inline void
-ecard_call(struct ecard_request *req)
-{
-	if (req->req == req_reset)
-		ecard_task_reset(req);
-	else
-		ecard_task_readbytes(req);
-}
+#define ecard_call(req)	ecard_do_request(req)
 #endif
 
 /* ======================= Mid-level card control ===================== */
+
 /*
- * This is called to reset the loaders for each expansion card on reboot.
+ * This function is responsible for resetting the expansion cards to a
+ * sensible state immediately prior to rebooting the system.  This function
+ * has process state (keventd), so we can sleep.
+ *
+ * Possible "val" values here:
+ *  SYS_RESTART   -  restarting system
+ *  SYS_HALT      - halting system
+ *  SYS_POWER_OFF - powering down system
  *
- * This is required to make sure that the card is in the correct state
- * that RiscOS expects it to be.
+ * 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.
  */
-void
-ecard_reset(int slot)
+static void ecard_reboot(struct notifier_block *me, unsigned long val, void *v)
 {
 	struct ecard_request req;
 
-	req.req = req_reset;
+	if (val != SYS_RESTART)
+		return;
 
-	if (slot < 0)
-		req.ec = NULL;
-	else
-		req.ec = slot_to_ecard(slot);
+	/*
+	 * Disable the expansion card interrupt
+	 */
+	disable_irq(IRQ_EXPANSIONCARD);
 
+	/*
+	 * If we have any expansion card loader code which will handle
+	 * the reset for us, call it now.
+	 */
+	req.req = req_reset_all;
 	ecard_call(&req);
 
+	/*
+	 * Disable the expansion card interrupt again, just to be sure.
+	 */
+	disable_irq(IRQ_EXPANSIONCARD);
+
+	/*
+	 * Finally, reset the expansion card interrupt mask to
+	 * all enable (RISC OS doesn't set this)
+	 */
 #ifdef HAS_EXPMASK
-	if (have_expmask && slot < 0) {
-		have_expmask |= ~0;
-		EXPMASK_ENABLE = have_expmask;
-	}
+	have_expmask = ~0;
+	__raw_writeb(have_expmask, EXPMASK_ENABLE);
 #endif
 }
 
+static struct notifier_block ecard_reboot_notifier = {
+	notifier_call:	ecard_reboot,
+};
+
+
+
 static void
 ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
 {
@@ -506,7 +501,7 @@
 #ifdef HAS_EXPMASK
 	if (irqnr < 4 && have_expmask) {
 		have_expmask |= 1 << irqnr;
-		EXPMASK_ENABLE = have_expmask;
+		__raw_writeb(have_expmask, EXPMASK_ENABLE);
 	}
 #endif
 }
@@ -516,7 +511,7 @@
 #ifdef HAS_EXPMASK
 	if (irqnr < 4 && have_expmask) {
 		have_expmask &= ~(1 << irqnr);
-		EXPMASK_ENABLE = have_expmask;
+		__raw_writeb(have_expmask, EXPMASK_ENABLE);
 	}
 #endif
 }
@@ -556,7 +551,7 @@
  *
  * They are not meant to be called directly, but via enable/disable_irq.
  */
-void ecard_enableirq(unsigned int irqnr)
+static void ecard_enableirq(unsigned int irqnr)
 {
 	ecard_t *ec = slot_to_ecard(irqnr - 32);
 
@@ -572,7 +567,7 @@
 	}
 }
 
-void ecard_disableirq(unsigned int irqnr)
+static void ecard_disableirq(unsigned int irqnr)
 {
 	ecard_t *ec = slot_to_ecard(irqnr - 32);
 
@@ -717,7 +712,7 @@
 	const unsigned int statusmask = 15;
 	unsigned int status;
 
-	status = EXPMASK_STATUS & statusmask;
+	status = __raw_readb(EXPMASK_STATUS) & statusmask;
 	if (status) {
 		unsigned int slot;
 		ecard_t *ec;
@@ -739,18 +734,21 @@
 			 * otherwise you will lose serial data at high speeds!
 			 */
 			oldexpmask = have_expmask;
-			EXPMASK_ENABLE = (have_expmask &= priority_masks[slot]);
+			have_expmask &= priority_masks[slot];
+			__raw_writeb(have_expmask, EXPMASK_ENABLE);
 			sti();
 			do_ecard_IRQ(ec->irq, regs);
 			cli();
-			EXPMASK_ENABLE = have_expmask = oldexpmask;
-			status = EXPMASK_STATUS & statusmask;
+			have_expmask = oldexpmask;
+			__raw_writeb(have_expmask, EXPMASK_ENABLE);
+			status = __raw_readb(EXPMASK_STATUS) & statusmask;
 			if (status)
 				goto again;
 		} else {
 			printk(KERN_WARNING "card%d: interrupt from unclaimed "
 			       "card???\n", slot);
-			EXPMASK_ENABLE = (have_expmask &= ~(1 << slot));
+			have_expmask &= ~(1 << slot);
+			__raw_writeb(have_expmask, EXPMASK_ENABLE);
 		}
 	} else
 		printk(KERN_WARNING "Wild interrupt from backplane (masks)\n");
@@ -762,10 +760,10 @@
 	ecard_t *ec;
 	int found;
 
-	EXPMASK_ENABLE = 0x00;
-	EXPMASK_STATUS = 0xff;
-	found = ((EXPMASK_STATUS & 15) == 0);
-	EXPMASK_ENABLE = 0xff;
+	__raw_writeb(0x00, EXPMASK_ENABLE);
+	__raw_writeb(0xff, EXPMASK_STATUS);
+	found = (__raw_readb(EXPMASK_STATUS) & 15) == 0;
+	__raw_writeb(0xff, EXPMASK_ENABLE);
 
 	if (!found)
 		return;
@@ -781,7 +779,7 @@
 	for (ec = cards; ec; ec = ec->next)
 		have_expmask |= 1 << ec->slot_no;
 
-	EXPMASK_ENABLE = have_expmask;
+	__raw_writeb(have_expmask, EXPMASK_ENABLE);
 }
 #else
 #define ecard_probeirqhw()
@@ -830,7 +828,7 @@
 	}
 
 #ifdef IOMD_ECTCR
-	outb(ectcr, IOMD_ECTCR);
+	iomd_writeb(ectcr, IOMD_ECTCR);
 #endif
 	return address;
 }
@@ -910,9 +908,8 @@
 	int i, rc = -ENOMEM;
 
 	ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
-
 	if (!ec)
-		goto nodev;
+		goto nomem;
 
 	memset(ec, 0, sizeof(ecard_t));
 
@@ -969,27 +966,31 @@
 	if (slot == 8)
 		ec->irq = 11;
 #endif
+	/*
+	 * hook the interrupt handlers
+	 */
+	if (ec->irq != 0 && ec->irq >= 32) {
+		irq_desc[ec->irq].mask_ack = ecard_disableirq;
+		irq_desc[ec->irq].mask     = ecard_disableirq;
+		irq_desc[ec->irq].unmask   = ecard_enableirq;
+		irq_desc[ec->irq].valid    = 1;
+	}
+
 #ifdef CONFIG_ARCH_RPC
 	/* On RiscPC, only first two slots have DMA capability */
 	if (slot < 2)
 		ec->dma = 2 + slot;
 #endif
-#if 0	/* We don't support FIQs on expansion cards at the moment */
-	ec->fiq = 96 + slot;
-#endif
-
-	rc = 0;
 
 	for (ecp = &cards; *ecp; ecp = &(*ecp)->next);
 
 	*ecp = ec;
+	slot_to_expcard[slot] = ec;
+	return 0;
 
 nodev:
-	if (rc && ec)
-		kfree(ec);
-	else
-		slot_to_expcard[slot] = ec;
-
+	kfree(ec);
+nomem:
 	return rc;
 }
 
@@ -1058,9 +1059,13 @@
 {
 	int slot;
 
+	/*
+	 * Register our reboot notifier
+	 */
+	register_reboot_notifier(&ecard_reboot_notifier);
+
 #ifdef CONFIG_CPU_32
 	init_waitqueue_head(&ecard_wait);
-	init_waitqueue_head(&ecard_done);
 #endif
 
 	printk("Probing expansion cards\n");
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
--- v2.4.3/linux/arch/arm/kernel/entry-armv.S	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/kernel/entry-armv.S	Thu Apr 12 12:20:31 2001
@@ -89,41 +89,52 @@
 		.if	ioc_base_low
 		orr	r4, r4, #ioc_base_low
 		.endif
-		ldrb	\irqstat, [r4, #0x24]		@ get high priority first
-		adr	\base, irq_prio_h
+		ldrb	\irqstat, [r4, #IOMD_IRQREQB]	@ get high priority first
+		ldr	\base, =irq_prio_h
 		teq	\irqstat, #0
 #ifdef IOMD_BASE
-		ldreqb	\irqstat, [r4, #0x1f4]		@ get dma
-		adreq	\base, irq_prio_d
+		ldreqb	\irqstat, [r4, #IOMD_DMAREQ]	@ get dma
+		addeq	\base, \base, #256		@ irq_prio_h table size
 		teqeq	\irqstat, #0
+		bne	2406f
 #endif
-		ldreqb	\irqstat, [r4, #0x14]		@ get low priority
-		adreq	\base, irq_prio_l
-
-		teq	\irqstat, #0
-		ldrneb	\irqnr, [\base, \irqstat]	@ get IRQ number
+		ldreqb	\irqstat, [r4, #IOMD_IRQREQA]	@ get low priority
+		addeq	\base, \base, #256		@ irq_prio_d table size
+		teqeq	\irqstat, #0
+#ifdef IOMD_IRQREQC
+		ldreqb	\irqstat, [r4, #IOMD_IRQREQC]
+		addeq	\base, \base, #256		@ irq_prio_l table size
+		teqeq	\irqstat, #0
+#endif
+#ifdef IOMD_IRQREQD
+		ldreqb	\irqstat, [r4, #IOMD_IRQREQD]
+		addeq	\base, \base, #256		@ irq_prio_lc table size
+		teqeq	\irqstat, #0
+#endif
+2406:		ldrneb	\irqnr, [\base, \irqstat]	@ get IRQ number
 		.endm
 
 /*
- * Interrupt table (incorporates priority)
+ * Interrupt table (incorporates priority).  Please note that we
+ * rely on the order of these tables (see above code).
  */
 		.macro	irq_prio_table
-irq_prio_l:	.byte	 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
-		.byte	 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
-		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
-		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
-		.byte	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
-		.byte	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
-		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
-		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
-		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+irq_prio_h:	.byte	 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
+		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
 #ifdef IOMD_BASE
 irq_prio_d:	.byte	 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
 		.byte	20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
@@ -142,26 +153,64 @@
 		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
 		.byte	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
 #endif
-irq_prio_h:	.byte	 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
-		.byte	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
+irq_prio_l:	.byte	 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
+		.byte	 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
+		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+		.byte	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
+		.byte	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
+		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+		.byte	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+		.byte	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+#ifdef IOMD_IRQREQC
+irq_prio_lc:	.byte	24,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27
+		.byte	28,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27
+		.byte	29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
+		.byte	29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
+		.byte	30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27
+		.byte	30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27
+		.byte	29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
+		.byte	29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
+		.byte	31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+		.byte	31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+		.byte	31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+		.byte	31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+		.byte	31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+		.byte	31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+		.byte	31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+		.byte	31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+#endif
+#ifdef IOMD_IRQREQD
+irq_prio_ld:	.byte	40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
+		.byte	44,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
+		.byte	45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
+		.byte	45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
+		.byte	46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43
+		.byte	46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43
+		.byte	45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
+		.byte	45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
+		.byte	47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
+		.byte	47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
+		.byte	47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
+		.byte	47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
+		.byte	47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
+		.byte	47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
+		.byte	47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
+		.byte	47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
+#endif
 		.endm
 
 #elif defined(CONFIG_ARCH_EBSA110)
 
+#define IRQ_STAT		0xff000000	/* read */
+
 		.macro	disable_fiq
 		.endm
 
@@ -457,7 +506,9 @@
 		.macro	irq_prio_table
 		.endm
 
-#elif defined(CONFIG_ARCH_P720T)
+#elif defined(CONFIG_ARCH_CLPS711X)
+
+#include <asm/hardware/clps7111.h>
 
 		.macro	disable_fiq
 		.endm
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S
--- v2.4.3/linux/arch/arm/kernel/entry-common.S	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/kernel/entry-common.S	Thu Apr 12 12:20:31 2001
@@ -35,9 +35,7 @@
 
 		.align	5
 fast_syscall_return:
-		str	r0, [sp, #S_R0 + S_OFF]	@ returned r0
-slow_syscall_return:
-		add	sp, sp, #S_OFF
+		str	r0, [sp, #S_R0+S_OFF]!	@ returned r0
 ret_from_sys_call:				@ external entry
 		get_softirq r0
 		get_current_task r5
@@ -52,6 +50,7 @@
 		bne	ret_reschedule
 		teq	r1, #0			@ check for signals
 		blne	ret_signal
+
 ret_from_all:	restore_user_regs		@ internal
 
 ret_signal:	mov	r1, sp			@ internal
@@ -132,7 +131,8 @@
 		str	ip, [sp, #S_IP + S_OFF]	@ trace exit [IP = 1]
 		bl	SYMBOL_NAME(syscall_trace)
 		str	tip, [sp, #S_IP + S_OFF]
-		b	slow_syscall_return
+		add	sp, sp, #S_OFF
+		b	ret_from_sys_call
 
 2:		add	r1, sp, #S_OFF
 		tst	scno, #0x00f00000	@ is it a Unix SWI?
@@ -142,8 +142,9 @@
 		b	SYMBOL_NAME(sys_ni_syscall) @ not private func
 
 3:		eor	r0, scno, #OS_NUMBER <<20	@ Put OS number back
-		adrsvc	al, lr, slow_syscall_return
-		b	SYMBOL_NAME(deferred)
+		bl	SYMBOL_NAME(deferred)
+		add	sp, sp, #S_OFF
+		b	ret_from_sys_call
 
 		.align	5
 		.type	__irq_stat, #object
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/fiq.c linux/arch/arm/kernel/fiq.c
--- v2.4.3/linux/arch/arm/kernel/fiq.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/kernel/fiq.c	Thu Apr 12 12:20:31 2001
@@ -124,7 +124,7 @@
 #ifdef CONFIG_CPU_26
 	"mov	%0, pc
 	bic	%1, %0, #0x3
-	orr	%1, %1, #0x0c000001
+	orr	%1, %1, %3
 	teqp	%1, #0		@ select FIQ mode
 	mov	r0, r0
 	ldmia	%2, {r8 - r14}
@@ -133,7 +133,7 @@
 #endif
 #ifdef CONFIG_CPU_32
 	"mrs	%0, cpsr
-	mov	%1, #0xc1
+	mov	%1, %3
 	msr	cpsr_c, %1	@ select FIQ mode
 	mov	r0, r0
 	ldmia	%2, {r8 - r14}
@@ -141,7 +141,7 @@
 	mov	r0, r0"
 #endif
 	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&regs->ARM_r8)
+	: "r" (&regs->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE)
 	/* These registers aren't modified by the above code in a way
 	   visible to the compiler, but we mark them as clobbers anyway
 	   so that GCC won't put any of the input or output operands in
@@ -156,7 +156,7 @@
 #ifdef CONFIG_CPU_26
 	"mov	%0, pc
 	bic	%1, %0, #0x3
-	orr	%1, %1, #0x0c000001
+	orr	%1, %1, %3
 	teqp	%1, #0		@ select FIQ mode
 	mov	r0, r0
 	stmia	%2, {r8 - r14}
@@ -165,7 +165,7 @@
 #endif
 #ifdef CONFIG_CPU_32
 	"mrs	%0, cpsr
-	mov	%1, #0xc1
+	mov	%1, %3
 	msr	cpsr_c, %1	@ select FIQ mode
 	mov	r0, r0
 	stmia	%2, {r8 - r14}
@@ -173,7 +173,7 @@
 	mov	r0, r0"
 #endif
 	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&regs->ARM_r8)
+	: "r" (&regs->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE)
 	/* These registers aren't modified by the above code in a way
 	   visible to the compiler, but we mark them as clobbers anyway
 	   so that GCC won't put any of the input or output operands in
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/head-armo.S linux/arch/arm/kernel/head-armo.S
--- v2.4.3/linux/arch/arm/kernel/head-armo.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/kernel/head-armo.S	Thu Apr 12 12:20:31 2001
@@ -82,9 +82,9 @@
 		mov	r1, #0
 		str	r0, [r1, #4]
 		ldr	r0, arm2_id
-		swp	r2, r2, [r1]		@ check for swp (ARM2 can't)
+		swp	r2, r2, [r1]		@ check for swp (ARM2 cant)
 		ldr	r0, arm250_id
-		mrc	15, 0, r3, c0, c0	@ check for CP#15 (ARM250 can't)
+		mrc	15, 0, r3, c0, c0	@ check for CP#15 (ARM250 cant)
 		mov	r0, r3
 continue:	mov	r2, #0xeb000000		@ Make undef vector loop
 		sub	r2, r2, #2
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S
--- v2.4.3/linux/arch/arm/kernel/head-armv.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/kernel/head-armv.S	Thu Apr 12 12:20:31 2001
@@ -26,7 +26,9 @@
  *
  * Note that swapper_pg_dir is the virtual address of the page tables, and
  * pgtbl gives us a position-independent reference to these tables.  We can
- * do this because stext == TEXT_ADDR
+ * do this because stext == TEXTADDR
+ *
+ * swapper_pg_dir, pgtbl and krnladr are all closely related.
  */
 #if (TEXTADDR & 0xffff) != 0x8000
 #error TEXTADDR must start at 0xXXXX8000
@@ -35,24 +37,36 @@
 		.globl	SYMBOL_NAME(swapper_pg_dir)
 		.equ	SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000
 
-		.macro	pgtbl, reg
+		.macro	pgtbl, reg, rambase
 		adr	\reg, stext
 		sub	\reg, \reg, #0x4000
 		.endm
 
+/*
+ * Since the page table is closely related to the kernel start address, we
+ * can convert the page table base address to the base address of the section
+ * containing both.
+ */
+		.macro	krnladr, rd, pgtable, rambase
+		bic	\rd, \pgtable, #0x000ff000
+		.endm
+
+/*
+ *  Kernel startup entry point.
+ *
+ * The rules are:
+ *  r0      - should be 0
+ *  r1      - unique architecture number
+ *  MMU     - off
+ *  I-cache - on or off
+ *  D-cache - off
+ *
+ * See linux/arch/arm/tools/mach-types for the complete list of numbers
+ * for r1.
+ */
 		.section ".text.init",#alloc,#execinstr
 		.type	stext, #function
 ENTRY(stext)
-/*
- * Entry point.  The general rules are:
- *  should be called with r0 == 0
- *  r1 contains the unique architecture number
- *  with MMU is off, I-cache may be on or off, D-cache should be off.
- * See linux/arch/arm/kernel/arch.c and linux/include/asm-arm/system.h
- * for the complete list of numbers for r1.  If you require a new number,
- * please follow the instructions given towards the end of
- * linux/Documentation/arm/README.
- */
 		mov	r12, r0
 /*
  * NOTE!  Any code which is placed here should be done for one of
@@ -115,7 +129,7 @@
 #endif
 
 		mov	r0, #F_BIT | I_BIT | MODE_SVC	@ make sure svc mode
-		msr	cpsr_c, r0			@ and all irqs diabled
+		msr	cpsr_c, r0			@ and all irqs disabled
 		bl	__lookup_processor_type
 		teq	r10, #0				@ invalid processor?
 		moveq	r0, #'p'			@ yes, error 'p'
@@ -129,6 +143,7 @@
 		add	pc, r10, #12			@ initialise processor
 							@ (return control reg)
 
+		.type	__switch_data, %object
 __switch_data:	.long	__mmap_switched
 		.long	SYMBOL_NAME(compat)
 		.long	SYMBOL_NAME(__bss_start)
@@ -138,6 +153,7 @@
 		.long	SYMBOL_NAME(cr_alignment)
 		.long	SYMBOL_NAME(init_task_union)+8192
 
+		.type	__ret, %function
 __ret:		ldr	lr, __switch_data
 		mcr	p15, 0, r0, c1, c0
 		mov	r0, r0
@@ -190,31 +206,37 @@
  * r8 = page table flags
  */
 __create_page_tables:
-		pgtbl	r4
+		pgtbl	r4, r5				@ page table address
+
+		/*
+		 * Clear the 16K level 1 swapper page table
+		 */
 		mov	r0, r4
 		mov	r3, #0
-		add	r2, r0, #0x4000			@ 16k of page table
-1:		str	r3, [r0], #4			@ Clear page table
+		add	r2, r0, #0x4000
+1:		str	r3, [r0], #4
 		str	r3, [r0], #4
 		str	r3, [r0], #4
 		str	r3, [r0], #4
 		teq	r0, r2
 		bne	1b
+
 		/*
-		 * Create identity mapping for first MB of kernel.
-		 * This is marked cacheable and bufferable.
-		 *
-		 * The identity mapping will be removed by  paging_init()
+		 * Create identity mapping for first MB of kernel to
+		 * cater for the MMU enable.  This identity mapping
+		 * will be removed by paging_init()
 		 */
-		add	r3, r8, r5			@ mmuflags + start of RAM
-		add	r0, r4, r5, lsr #18
-		str	r3, [r0]			@ identity mapping
+		krnladr	r2, r4, r5			@ start of kernel
+		add	r3, r8, r2			@ flags + kernel base
+		str	r3, [r4, r2, lsr #18]		@ identity mapping
+
 		/*
 		 * Now setup the pagetables for our kernel direct
 		 * mapped region.  We round TEXTADDR down to the
 		 * nearest megabyte boundary.
 		 */
-		add	r0, r4, #(TEXTADDR & 0xfff00000) >> 18 @ start of kernel
+		add	r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel
+		add	r0, r0, #(TEXTADDR & 0x00f00000) >> 18
 		str	r3, [r0], #4			@ PAGE_OFFSET + 0MB
 		add	r3, r3, #1 << 20
 		str	r3, [r0], #4			@ PAGE_OFFSET + 1MB
@@ -223,13 +245,25 @@
 		add	r3, r3, #1 << 20
 		str	r3, [r0], #4			@ PAGE_OFFSET + 3MB
 
+		/*
+		 * Ensure that the first section of RAM is present.
+		 * we assume that:
+		 *  1. the RAM is aligned to a 256MB boundary
+		 *  2. the kernel is executing in the same 256MB chunk
+		 *     as the start of RAM.
+		 */
+		bic	r0, r0, #0x0ff00000 >> 18	@ round down
+		and	r2, r5, #0xf0000000		@ round down
+		add	r3, r8, r2			@ flags + rambase
+		str	r3, [r0]
+
 		bic	r8, r8, #0x0c			@ turn off cacheable
 							@ and bufferable bits
 #ifdef CONFIG_DEBUG_LL
 		/*
 		 * Map in IO space for serial debugging.
 		 * This allows debug messages to be output
-		 * via a serial before paging_init.
+		 * via a serial console before paging_init.
 		 */
 		add	r0, r4, r7
 		rsb	r3, r7, #0x4000	@ PTRS_PER_PGD*sizeof(long)
@@ -241,12 +275,13 @@
 		add	r3, r3, #1 << 20
 		teq	r0, r2
 		bne	1b
-#ifdef CONFIG_ARCH_NETWINDER
+#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
 		/*
 		 * If we're using the NetWinder, we need to map in
 		 * the 16550-type serial port for the debug messages
 		 */
-		teq	r1, #5
+		teq	r1, #MACH_TYPE_NETWINDER
+		teqne	r1, #MACH_TYPE_CATS
 		bne	1f
 		add	r0, r4, #0x3fc0
 		mov	r3, #0x7c000000
@@ -263,13 +298,12 @@
 		 * Similar reasons here - for debug.  This is
 		 * only for Acorn RiscPC architectures.
 		 */
-		teq	r5, #0
-		addne	r0, r4, #0x80			@ 02000000
-		movne	r3, #0x02000000
-		orrne	r3, r3, r8
-		strne	r3, [r0]
-		addne	r0, r4, #0x3600			@ d8000000
-		strne	r3, [r0]
+		add	r0, r4, #0x80			@ 02000000
+		mov	r3, #0x02000000
+		orr	r3, r3, r8
+		str	r3, [r0]
+		add	r0, r4, #0x3600			@ d8000000
+		str	r3, [r0]
 #endif
 		mov	pc, lr
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/io.c linux/arch/arm/kernel/io.c
--- v2.4.3/linux/arch/arm/kernel/io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/io.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,49 @@
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+/*
+ * Copy data from IO memory space to "real" memory space.
+ * This needs to be optimized.
+ */
+void _memcpy_fromio(void * to, unsigned long from, size_t count)
+{
+	while (count) {
+		count--;
+		*(char *) to = readb(from);
+		((char *) to)++;
+		from++;
+	}
+}
+
+/*
+ * Copy data from "real" memory space to IO memory space.
+ * This needs to be optimized.
+ */
+void _memcpy_toio(unsigned long to, const void * from, size_t count)
+{
+	while (count) {
+		count--;
+		writeb(*(char *) from, to);
+		((char *) from)++;
+		to++;
+	}
+}
+
+/*
+ * "memset" on IO memory space.
+ * This needs to be optimized.
+ */
+void _memset_io(unsigned long dst, int c, size_t count)
+{
+	while (count) {
+		count--;
+		writeb(c, dst);
+		dst++;
+	}
+}
+
+EXPORT_SYMBOL(_memcpy_fromio);
+EXPORT_SYMBOL(_memcpy_toio);
+EXPORT_SYMBOL(_memset_io);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/irq-arch.c linux/arch/arm/kernel/irq-arch.c
--- v2.4.3/linux/arch/arm/kernel/irq-arch.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/irq-arch.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,41 @@
+/*
+ *  linux/arch/arm/kernel/irq-arch.c
+ *
+ *  Copyright (C) 1995-2000 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
+ * published by the Free Software Foundation.
+ *
+ *  We contain the architecture-specific parts of interrupt handling
+ *  in this file.  In 2.5, it will move into the various arch/arm/mach-*
+ *  directories.
+ */
+#include <linux/ptrace.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <asm/mach/irq.h>
+
+/*
+ * Get architecture specific interrupt handlers
+ * and interrupt initialisation.
+ */
+#include <asm/arch/irq.h>
+
+void __init genarch_init_irq(void)
+{
+	irq_init_irq();
+}
+
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c
--- v2.4.3/linux/arch/arm/kernel/irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/arm/kernel/irq.c	Thu Apr 12 12:20:31 2001
@@ -2,7 +2,7 @@
  *  linux/arch/arm/kernel/irq.c
  *
  *  Copyright (C) 1992 Linus Torvalds
- *  Modifications for ARM processor Copyright (C) 1995-1998 Russell King.
+ *  Modifications for ARM processor Copyright (C) 1995-2000 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
@@ -29,9 +29,11 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 
-#include <asm/hardware.h>
-#include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/irq.h>	/* pick up fixup_irq definition */
 
 /*
  * Maximum IRQ count.  Currently, this is arbitary.  However, it should
@@ -42,41 +44,11 @@
  */
 #define MAX_IRQ_CNT	100000
 
-spinlock_t irq_controller_lock;
-
-int setup_arm_irq(int, struct irqaction *);
-extern int get_fiq_list(char *);
-extern void init_FIQ(void);
-
-struct irqdesc {
-	unsigned int	 nomask   : 1;		/* IRQ does not mask in IRQ   */
-	unsigned int	 enabled  : 1;		/* IRQ is currently enabled   */
-	unsigned int	 triggered: 1;		/* IRQ has occurred	      */
-	unsigned int	 probing  : 1;		/* IRQ in use for a probe     */
-	unsigned int	 probe_ok : 1;		/* IRQ can be used for probe  */
-	unsigned int	 valid    : 1;		/* IRQ claimable	      */
-	unsigned int	 noautoenable : 1;	/* don't automatically enable IRQ */
-	unsigned int	 unused   :25;
-	void (*mask_ack)(unsigned int irq);	/* Mask and acknowledge IRQ   */
-	void (*mask)(unsigned int irq);		/* Mask IRQ		      */
-	void (*unmask)(unsigned int irq);	/* Unmask IRQ		      */
-	struct irqaction *action;
-	/*
-	 * IRQ lock detection
-	 */
-	unsigned int	 lck_cnt;
-	unsigned int	 lck_pc;
-	unsigned int	 lck_jif;
-};
-
-static struct irqdesc irq_desc[NR_IRQS];
 static volatile unsigned long irq_err_count;
+static spinlock_t irq_controller_lock;
 
-/*
- * Get architecture specific interrupt handlers
- * and interrupt initialisation.
- */
-#include <asm/arch/irq.h>
+struct irqdesc irq_desc[NR_IRQS];
+void (*init_arch_irq)(void) __initdata = NULL;
 
 /*
  * Dummy mask/unmask handler
@@ -85,6 +57,14 @@
 {
 }
 
+/**
+ *	disable_irq - disable an irq and wait for completion
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
 void disable_irq(unsigned int irq)
 {
 	unsigned long flags;
@@ -95,6 +75,14 @@
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
 }
 
+/**
+ *	enable_irq - enable interrupt handling on an irq
+ *	@irq: Interrupt to enable
+ *
+ *	Re-enables the processing of interrupts on this IRQ line
+ *
+ *	This function may be called from IRQ context.
+ */
 void enable_irq(unsigned int irq)
 {
 	unsigned long flags;
@@ -271,6 +259,7 @@
 	int shared = 0;
 	struct irqaction *old, **p;
 	unsigned long flags;
+	struct irqdesc *desc;
 
 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
@@ -292,8 +281,9 @@
 	/*
 	 * The following block of code has to be executed atomically
 	 */
+	desc = irq_desc + irq;
 	spin_lock_irqsave(&irq_controller_lock, flags);
-	p = &irq_desc[irq].action;
+	p = &desc->action;
 	if ((old = *p) != NULL) {
 		/* Can't share interrupts unless both agree to */
 		if (!(old->flags & new->flags & SA_SHIRQ)) {
@@ -312,11 +302,11 @@
 	*p = new;
 
 	if (!shared) {
-		irq_desc[irq].nomask = (new->flags & SA_IRQNOMASK) ? 1 : 0;
-		irq_desc[irq].probing = 0;
-		if (!irq_desc[irq].noautoenable) {
-			irq_desc[irq].enabled = 1;
-			irq_desc[irq].unmask(irq);
+		desc->nomask = (new->flags & SA_IRQNOMASK) ? 1 : 0;
+		desc->probing = 0;
+		if (!desc->noautoenable) {
+			desc->enabled = 1;
+			desc->unmask(irq);
 		}
 	}
 
@@ -324,13 +314,45 @@
 	return 0;
 }
 
+/**
+ *	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 irq_flags, const char * devname, void *dev_id)
 {
 	unsigned long retval;
 	struct irqaction *action;
 
-	if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler)
+	if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler ||
+	    (irq_flags & SA_SHIRQ && !dev_id))
 		return -EINVAL;
 
 	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
@@ -351,6 +373,18 @@
 	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.
+ *
+ *	This function may be called from interrupt context.
+ */
 void free_irq(unsigned int irq, void *dev_id)
 {
 	struct irqaction * action, **p;
@@ -486,6 +520,6 @@
 		irq_desc[irq].unmask   = dummy_mask_unmask_irq;
 	}
 
-	irq_init_irq();
+	init_arch_irq();
 	init_dma();
 }
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/leds-ebsa110.c linux/arch/arm/kernel/leds-ebsa110.c
--- v2.4.3/linux/arch/arm/kernel/leds-ebsa110.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/kernel/leds-ebsa110.c	Wed Dec 31 16:00:00 1969
@@ -1,51 +0,0 @@
-/*
- *  linux/arch/arm/kernel/leds-ebsa110.c
- *
- *  Copyright (C) 1998 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
- * published by the Free Software Foundation.
- *
- *  EBSA-110 LED control routines.  We use the led as follows:
- *
- *   - Red - toggles state every 50 timer interrupts
- */
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/leds.h>
-#include <asm/system.h>
-#include <asm/mach-types.h>
-
-static spinlock_t leds_lock;
-
-static void ebsa110_leds_event(led_event_t ledevt)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&leds_lock, flags);
-
-	switch(ledevt) {
-	case led_timer:
-		*(volatile unsigned char *)0xf2400000 ^= 128;
-		break;
-
-	default:
-		break;
-	}
-
-	spin_unlock_irqrestore(&leds_lock, flags);
-}
-
-static int __init leds_init(void)
-{
-	if (machine_is_ebsa110())
-		leds_event = ebsa110_leds_event;
-
-	return 0;
-}
-
-__initcall(leds_init);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/oldlatches.c linux/arch/arm/kernel/oldlatches.c
--- v2.4.3/linux/arch/arm/kernel/oldlatches.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/kernel/oldlatches.c	Thu Apr 12 12:20:31 2001
@@ -59,7 +59,7 @@
 	}
 }
 
-initcall(oldlatch_init);
+__initcall(oldlatch_init);
 
 EXPORT_SYMBOL(oldlatch_aupdate);
 EXPORT_SYMBOL(oldlatch_bupdate);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/semaphore.c linux/arch/arm/kernel/semaphore.c
--- v2.4.3/linux/arch/arm/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/arm/kernel/semaphore.c	Tue Apr 17 17:19:24 2001
@@ -165,321 +165,3 @@
 	spin_unlock_irqrestore(&semaphore_lock, flags);
 	return 1;
 }
-
-struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->read_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem)
-{
-        struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (atomic_read(&sem->count) >= 0)
-		wake_up(&sem->wait);
-
-	return sem;
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-struct rw_semaphore *down_read_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	/* this takes care of granting the lock */
-	__up_op_read(sem, __rwsem_wake);
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-struct rw_semaphore *down_write_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	/* this takes care of granting the lock */
-	__up_op_write(sem, __rwsem_wake);
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->read_bias_granted, 1))
-		BUG();
-	wake_up(&sem->wait);
-	return sem;
-}
-
-struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->write_bias_granted, 1))
-		BUG();
-	wake_up(&sem->write_bias_wait);
-	return sem;
-}
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- *
- * ip contains the semaphore pointer on entry. Save the C-clobbered
- * registers (r0 to r3 and lr), but not ip, as we use it as a return
- * value in some cases..
- */
-#ifdef CONFIG_CPU_26
-asm("	.section	.text.lock, \"ax\"
-	.align	5
-	.globl	__down_failed
-__down_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.align	5
-	.globl	__down_interruptible_failed
-__down_interruptible_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down_interruptible
-	mov	ip, r0
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.align	5
-	.globl	__down_trylock_failed
-__down_trylock_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down_trylock
-	mov	ip, r0
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.align	5
-	.globl	__up_wakeup
-__up_wakeup:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__up
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.align	5
-	.globl	__down_read_failed
-__down_read_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bcc	1f
-1:	bl	down_read_failed_biased
-	ldmfd	sp!, {r0 - r3, pc}^
-2:	bl	down_read_failed
-	mov	r1, pc
-	orr	r2, r1, #
-	teqp r2, #0
-
-	ldr	r3, [r0]
-	subs	r3, r3, #1
-	str	r3, [r0]
-	ldmplfd	sp!, {r0 - r3, pc}^
-  orrcs r1, r1, #0x20000000   @ Set carry
-  teqp r1, #0
-	bcc	2b
-	b	1b
-
-	.align	5
-	.globl	__down_write_failed
-__down_write_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bcc	1f
-1:	bl	down_write_failed_biased
-	ldmfd	sp!, {r0 - r3, pc}^
-2:	bl	down_write_failed
-	mov r1, pc
-	orr	r2, r1, #128
-	teqp r2, #0
-
-	ldr	r3, [r0]
-	subs	r3, r3, #"RW_LOCK_BIAS_STR"
-	str	r3, [r0]
-	ldmeqfd	sp!, {r0 - r3, pc}^
-  orrcs r1, r1, #0x20000000   @ Set carry
-	teqp r1, #0
-	bcc	2b
-	b	1b
-
-	.align	5
-	.globl	__rwsem_wake
-__rwsem_wake:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	beq	1f
-	bl	rwsem_wake_readers
-	ldmfd	sp!, {r0 - r3, pc}^
-1:	bl	rwsem_wake_writer
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.previous
-	");
-
-#else
-/* 32 bit version */
-asm("	.section	.text.lock, \"ax\"
-	.align	5
-	.globl	__down_failed
-__down_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.align	5
-	.globl	__down_interruptible_failed
-__down_interruptible_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down_interruptible
-	mov	ip, r0
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.align	5
-	.globl	__down_trylock_failed
-__down_trylock_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down_trylock
-	mov	ip, r0
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.align	5
-	.globl	__up_wakeup
-__up_wakeup:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__up
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.align	5
-	.globl	__down_read_failed
-__down_read_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bcc	1f
-1:	bl	down_read_failed_biased
-	ldmfd	sp!, {r0 - r3, pc}
-2:	bl	down_read_failed
-	mrs	r1, cpsr
-	orr	r2, r1, #128
-	msr	cpsr_c, r2
-	ldr	r3, [r0]
-	subs	r3, r3, #1
-	str	r3, [r0]
-	msr	cpsr_c, r1
-	ldmplfd	sp!, {r0 - r3, pc}
-	bcc	2b
-	b	1b
-
-	.align	5
-	.globl	__down_write_failed
-__down_write_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bcc	1f
-1:	bl	down_write_failed_biased
-	ldmfd	sp!, {r0 - r3, pc}
-2:	bl	down_write_failed
-	mrs	r1, cpsr
-	orr	r2, r1, #128
-	msr	cpsr_c, r2
-	ldr	r3, [r0]
-	subs	r3, r3, #"RW_LOCK_BIAS_STR"
-	str	r3, [r0]
-	msr	cpsr_c, r1
-	ldmeqfd	sp!, {r0 - r3, pc}
-	bcc	2b
-	b	1b
-
-	.align	5
-	.globl	__rwsem_wake
-__rwsem_wake:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	beq	1f
-	bl	rwsem_wake_readers
-	ldmfd	sp!, {r0 - r3, pc}
-1:	bl	rwsem_wake_writer
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.previous
-	");
-
-#endif
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- v2.4.3/linux/arch/arm/kernel/setup.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/kernel/setup.c	Thu Apr 12 12:20:31 2001
@@ -26,6 +26,7 @@
 #include <asm/mach-types.h>
 
 #include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
 
 #ifndef MEM_SIZE
 #define MEM_SIZE	(16*1024*1024)
@@ -35,10 +36,21 @@
 #define CONFIG_CMDLINE ""
 #endif
 
+#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
+char fpe_type[8];
+
+static int __init fpe_setup(char *line)
+{
+	memcpy(fpe_type, line, 8);
+	return 1;
+}
+
+__setup("fpe=", fpe_setup);
+#endif
+
 extern void paging_init(struct meminfo *, struct machine_desc *desc);
 extern void bootmem_init(struct meminfo *);
 extern void reboot_setup(char *str);
-extern void disable_hlt(void);
 extern unsigned long memparse(char *ptr, char **retptr);
 extern int root_mountflags;
 extern int _stext, _text, _etext, _edata, _end;
@@ -71,9 +83,10 @@
 char elf_platform[ELF_PLATFORM_SIZE];
 char saved_command_line[COMMAND_LINE_SIZE];
 
+static struct meminfo meminfo __initdata = { 0, };
 static struct proc_info_item proc_info;
 static const char *machine_name;
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+static char command_line[COMMAND_LINE_SIZE];
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
@@ -306,71 +319,222 @@
 		request_resource(&ioport_resource, &lp2);
 }
 
+/*
+ *  Tag parsing.
+ *
+ * This is the new way of passing data to the kernel at boot time.  Rather
+ * than passing a fixed inflexible structure to the kernel, we pass a list
+ * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
+ * tag for the list to be recognised (to distinguish the tagged list from
+ * a param_struct).  The list is terminated with a zero-length tag (this tag
+ * is not parsed in any way).
+ */
+static int __init parse_tag_core(const struct tag *tag)
+{
+	if ((tag->u.core.flags & 1) == 0)
+		root_mountflags &= ~MS_RDONLY;
+	ROOT_DEV = to_kdev_t(tag->u.core.rootdev);
+	return 0;
+}
+
+static int __init parse_tag_mem32(const struct tag *tag)
+{
+	if (meminfo.nr_banks >= NR_BANKS) {
+		printk(KERN_WARNING
+		       "Ignoring memory bank 0x%08x size %dKB\n",
+			tag->u.mem.start, tag->u.mem.size / 1024);
+		return -EINVAL;
+	}
+	meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start;
+	meminfo.bank[meminfo.nr_banks].size  = tag->u.mem.size;
+	meminfo.bank[meminfo.nr_banks].node  = 0;
+	meminfo.nr_banks += 1;
+
+	return 0;
+}
+
+static int __init parse_tag_videotext(const struct tag *tag)
+{
+	screen_info.orig_x            = tag->u.videotext.x;
+	screen_info.orig_y            = tag->u.videotext.y;
+	screen_info.orig_video_page   = tag->u.videotext.video_page;
+	screen_info.orig_video_mode   = tag->u.videotext.video_mode;
+	screen_info.orig_video_cols   = tag->u.videotext.video_cols;
+	screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
+	screen_info.orig_video_lines  = tag->u.videotext.video_lines;
+	screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
+	screen_info.orig_video_points = tag->u.videotext.video_points;
+	return 0;
+}
+
+static int __init parse_tag_ramdisk(const struct tag *tag)
+{
+	setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
+		      (tag->u.ramdisk.flags & 2) == 0,
+		      tag->u.ramdisk.start, tag->u.ramdisk.size);
+	return 0;
+}
+
+static int __init parse_tag_initrd(const struct tag *tag)
+{
+	setup_initrd(tag->u.initrd.start, tag->u.initrd.size);
+	return 0;
+}
+
+static int __init parse_tag_serialnr(const struct tag *tag)
+{
+	system_serial_low = tag->u.serialnr.low;
+	system_serial_high = tag->u.serialnr.high;
+	return 0;
+}
+
+static int __init parse_tag_revision(const struct tag *tag)
+{
+	system_rev = tag->u.revision.rev;
+	return 0;
+}
+
+static int __init parse_tag_cmdline(const struct tag *tag)
+{
+	strncpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
+	default_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+	return 0;
+}
+
+/*
+ * This is the core tag table; these are the tags
+ * that we recognise for any machine type.
+ */
+static const struct tagtable core_tagtable[] __init = {
+	{ ATAG_CORE,      parse_tag_core      },
+	{ ATAG_MEM,       parse_tag_mem32     },
+	{ ATAG_VIDEOTEXT, parse_tag_videotext },
+	{ ATAG_RAMDISK,   parse_tag_ramdisk   },
+	{ ATAG_INITRD,    parse_tag_initrd    },
+	{ ATAG_SERIAL,    parse_tag_serialnr  },
+	{ ATAG_REVISION,  parse_tag_revision  },
+	{ ATAG_CMDLINE,   parse_tag_cmdline   }
+};
+
+/*
+ * Scan one tag table for this tag, and call its parse function.
+ */
+static int __init
+parse_tag(const struct tagtable *tbl, int size, const struct tag *t)
+{
+	int i;
+
+	for (i = 0; i < size; i++, tbl++)
+		if (t->hdr.tag == tbl->tag) {
+			tbl->parse(t);
+			break;
+		}
+
+	return i < size;
+}
+
+/*
+ * Parse all tags in the list, checking both the global and architecture
+ * specific tag tables.
+ */
+static void __init
+parse_tags(const struct tagtable *tbl, int size, const struct tag *t)
+{
+	/*
+	 * The tag list is terminated with a zero-sized tag.  Size is
+	 * defined to be in units of 32-bit quantities.
+	 */
+	for (; t->hdr.size; t = (struct tag *)((u32 *)t + t->hdr.size)) {
+		if (parse_tag(core_tagtable, ARRAY_SIZE(core_tagtable), t))
+			continue;
+
+		if (tbl && parse_tag(tbl, size, t))
+			continue;
+
+		printk(KERN_WARNING
+		       "Ignoring unrecognised tag 0x%08x\n", t->hdr.tag);
+	}
+}
+
+static void __init parse_params(struct param_struct *params)
+{
+	if (params->u1.s.page_size != PAGE_SIZE) {
+		printk(KERN_WARNING "Warning: bad configuration page, "
+		       "trying to continue\n");
+		return;
+	}
+
+	ROOT_DEV	   = to_kdev_t(params->u1.s.rootdev);
+	system_rev	   = params->u1.s.system_rev;
+	system_serial_low  = params->u1.s.system_serial_low;
+	system_serial_high = params->u1.s.system_serial_high;
+
+	if (params->u1.s.mem_fclk_21285 > 0)
+		mem_fclk_21285 = params->u1.s.mem_fclk_21285;  
+
+	setup_ramdisk((params->u1.s.flags & FLAG_RDLOAD) == 0,
+		      (params->u1.s.flags & FLAG_RDPROMPT) == 0,
+		      params->u1.s.rd_start,
+		      params->u1.s.ramdisk_size);
+
+	setup_initrd(params->u1.s.initrd_start,
+		     params->u1.s.initrd_size);
+
+	if (!(params->u1.s.flags & FLAG_READONLY))
+		root_mountflags &= ~MS_RDONLY;
+
+	strncpy(default_command_line, params->commandline, COMMAND_LINE_SIZE);
+	default_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+
+	if (meminfo.nr_banks == 0) {
+		meminfo.nr_banks      = 1;
+		meminfo.bank[0].start = PHYS_OFFSET;
+		meminfo.bank[0].size  = params->u1.s.nr_pages << PAGE_SHIFT;
+	}
+}
+
 void __init setup_arch(char **cmdline_p)
 {
 	struct param_struct *params = NULL;
 	struct machine_desc *mdesc;
-	struct meminfo meminfo;
 	char *from = default_command_line;
 
-	memset(&meminfo, 0, sizeof(meminfo));
-
-	setup_processor();
-
 	ROOT_DEV = MKDEV(0, 255);
 
+	setup_processor();
 	mdesc = setup_architecture(machine_arch_type);
 	machine_name = mdesc->name;
 
-	if (mdesc->broken_hlt)
-		disable_hlt();
-
 	if (mdesc->soft_reboot)
 		reboot_setup("s");
 
 	if (mdesc->param_offset)
 		params = phys_to_virt(mdesc->param_offset);
 
+	/*
+	 * Do the machine-specific fixups before we parse the
+	 * parameters or tags.
+	 */
 	if (mdesc->fixup)
 		mdesc->fixup(mdesc, params, &from, &meminfo);
 
-	if (params && params->u1.s.page_size != PAGE_SIZE) {
-		printk(KERN_WARNING "Warning: bad configuration page, "
-		       "trying to continue\n");
-		params = NULL;
-	}
-
 	if (params) {
-		ROOT_DEV	   = to_kdev_t(params->u1.s.rootdev);
-		system_rev	   = params->u1.s.system_rev;
-		system_serial_low  = params->u1.s.system_serial_low;
-		system_serial_high = params->u1.s.system_serial_high;
-
-		if (params->u1.s.mem_fclk_21285 > 0)
-			mem_fclk_21285 = params->u1.s.mem_fclk_21285;  
-
-		setup_ramdisk((params->u1.s.flags & FLAG_RDLOAD) == 0,
-			      (params->u1.s.flags & FLAG_RDPROMPT) == 0,
-			      params->u1.s.rd_start,
-			      params->u1.s.ramdisk_size);
-
-		setup_initrd(params->u1.s.initrd_start,
-			     params->u1.s.initrd_size);
-
-		if (!(params->u1.s.flags & FLAG_READONLY))
-			root_mountflags &= ~MS_RDONLY;
+		struct tag *tag = (struct tag *)params;
 
-		from = params->commandline;
+		/*
+		 * Is the first tag the CORE tag?  This differentiates
+		 * between the tag list and the parameter table.
+		 */
+		if (tag->hdr.tag == ATAG_CORE)
+			parse_tags(mdesc->tagtable, mdesc->tagsize, tag);
+		else
+			parse_params(params);
 	}
 
 	if (meminfo.nr_banks == 0) {
 		meminfo.nr_banks      = 1;
 		meminfo.bank[0].start = PHYS_OFFSET;
-		meminfo.bank[0].node  = 0;
-		if (params)
-			meminfo.bank[0].size = params->u1.s.nr_pages << PAGE_SHIFT;
-		else
-			meminfo.bank[0].size = MEM_SIZE;
+		meminfo.bank[0].size  = MEM_SIZE;
 	}
 
 	init_mm.start_code = (unsigned long) &_text;
@@ -385,6 +549,11 @@
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
 
+	/*
+	 * Set up various architecture-specific pointers
+	 */
+	init_arch_irq = mdesc->init_irq;
+
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
@@ -403,8 +572,8 @@
 		     (int)processor_id & 15, elf_platform);
 
 	p += sprintf(p, "BogoMIPS\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);
 
 	p += sprintf(p, "Hardware\t: %s\n", machine_name);
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/time-acorn.c linux/arch/arm/kernel/time-acorn.c
--- v2.4.3/linux/arch/arm/kernel/time-acorn.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/kernel/time-acorn.c	Thu Apr 12 12:20:31 2001
@@ -28,17 +28,17 @@
 	unsigned int count1, count2, status1, status2;
 	unsigned long offset = 0;
 
-	status1 = inb(IOC_IRQREQA);
+	status1 = ioc_readb(IOC_IRQREQA);
 	barrier ();
-	outb (0, IOC_T0LATCH);
+	ioc_writeb (0, IOC_T0LATCH);
 	barrier ();
-	count1 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8);
+	count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
 	barrier ();
-	status2 = inb(IOC_IRQREQA);
+	status2 = ioc_readb(IOC_IRQREQA);
 	barrier ();
-	outb (0, IOC_T0LATCH);
+	ioc_writeb (0, IOC_T0LATCH);
 	barrier ();
-	count2 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8);
+	count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
 
 	if (count2 < count1) {
 		/*
@@ -67,9 +67,9 @@
 
 void __init ioctime_init(void)
 {
-	outb(LATCH & 255, IOC_T0LTCHL);
-	outb(LATCH >> 8, IOC_T0LTCHH);
-	outb(0, IOC_T0GO);
+	ioc_writeb(LATCH & 255, IOC_T0LTCHL);
+	ioc_writeb(LATCH >> 8, IOC_T0LTCHH);
+	ioc_writeb(0, IOC_T0GO);
 
 	gettimeoffset = ioctime_gettimeoffset;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/arm/kernel/via82c505.c linux/arch/arm/kernel/via82c505.c
--- v2.4.3/linux/arch/arm/kernel/via82c505.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/kernel/via82c505.c	Thu Apr 12 12:20:31 2001
@@ -106,8 +106,8 @@
 	    break;
 	  case PCI_BASE_ADDRESS_0:
 	    if (size_wanted) {
-	      /* 0x00900000 bytes long */
-	      *value = 0xff700000;
+	      /* 0x00900000 bytes long (0xff700000) */
+	      *value = 0xff000000;
 	      size_wanted = 0;
 	    } else {
 	      *value = FB_START;
@@ -117,7 +117,7 @@
 	    *value = 6;
 	    break;
 	  default:
-	    *value=0;
+	    *value = 0;
 	  }
 	return PCIBIOS_SUCCESSFUL;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- v2.4.3/linux/arch/arm/lib/Makefile	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/lib/Makefile	Thu Apr 12 12:20:31 2001
@@ -17,8 +17,6 @@
 obj-m		:=
 obj-n		:=
 
-export-objs	:= io.o
-
 obj-arc		:= ecard.o io-acorn.o floppydma.o
 obj-rpc		:= ecard.o io-acorn.o floppydma.o
 obj-clps7500	:= io-acorn.o
@@ -47,10 +45,6 @@
 
 ifeq ($(PROCESSOR),armo)
   obj-y		+= uaccess-armo.o
-endif
-
-ifneq ($(MACHINE),ebsa110)
-  obj-y		+= io.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/arm/lib/backtrace.S linux/arch/arm/lib/backtrace.S
--- v2.4.3/linux/arch/arm/lib/backtrace.S	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/lib/backtrace.S	Thu Apr 12 12:20:31 2001
@@ -26,7 +26,7 @@
 
 ENTRY(c_backtrace)
 
-#ifndef CONFIG_FRAME_POINTER
+#ifdef CONFIG_NO_FRAME_POINTER
 		mov	pc, lr
 #else
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/lib/delay.S linux/arch/arm/lib/delay.S
--- v2.4.3/linux/arch/arm/lib/delay.S	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/lib/delay.S	Thu Apr 12 12:20:31 2001
@@ -11,19 +11,26 @@
 #include <asm/assembler.h>
 		.text
 
-LC0:		.word	SYMBOL_NAME(loops_per_sec)
+LC0:		.word	SYMBOL_NAME(loops_per_jiffy)
 
+/*
+ * 0 <= r0 <= 2000
+ */
 ENTRY(udelay)
-		mov	r2, #0x1000
-		orr	r2, r2, #0x00c6
+		mov	r2,     #0x6800
+		orr	r2, r2, #0x00db
 		mul	r1, r0, r2
 		ldr	r2, LC0
 		ldr	r2, [r2]
 		mov	r1, r1, lsr #11
 		mov	r2, r2, lsr #11
 		mul	r0, r1, r2
-		movs	r0, r0, lsr #10
+		movs	r0, r0, lsr #6
 		RETINSTR(moveq,pc,lr)
+
+/*
+ * loops = (r0 * 0x10c6 * 100 * loops_per_jiffie) / 2^32
+ */
 
 @ Delay routine
 ENTRY(__delay)
diff -u --recursive --new-file v2.4.3/linux/arch/arm/lib/io-shark.c linux/arch/arm/lib/io-shark.c
--- v2.4.3/linux/arch/arm/lib/io-shark.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/lib/io-shark.c	Thu Apr 12 12:20:31 2001
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/lib/io-shark.c
  *
- *  by Alexander.Schulz@stud.uni-karlsruhe.de
+ *  by Alexander Schulz <aschulz@netwinder.org>
  *
  * derived from:
  * linux/arch/arm/lib/io-ebsa.S
diff -u --recursive --new-file v2.4.3/linux/arch/arm/lib/io.c linux/arch/arm/lib/io.c
--- v2.4.3/linux/arch/arm/lib/io.c	Sun Feb  6 17:45:25 2000
+++ linux/arch/arm/lib/io.c	Wed Dec 31 16:00:00 1969
@@ -1,50 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-
-#include <asm/io.h>
-
-/*
- * Copy data from IO memory space to "real" memory space.
- * This needs to be optimized.
- */
-void _memcpy_fromio(void * to, unsigned long from, size_t count)
-{
-	while (count) {
-		count--;
-		*(char *) to = readb(from);
-		((char *) to)++;
-		from++;
-	}
-}
-
-/*
- * Copy data from "real" memory space to IO memory space.
- * This needs to be optimized.
- */
-void _memcpy_toio(unsigned long to, const void * from, size_t count)
-{
-	while (count) {
-		count--;
-		writeb(*(char *) from, to);
-		((char *) from)++;
-		to++;
-	}
-}
-
-/*
- * "memset" on IO memory space.
- * This needs to be optimized.
- */
-void _memset_io(unsigned long dst, int c, size_t count)
-{
-	while (count) {
-		count--;
-		writeb(c, dst);
-		dst++;
-	}
-}
-
-EXPORT_SYMBOL(_memcpy_fromio);
-EXPORT_SYMBOL(_memcpy_toio);
-EXPORT_SYMBOL(_memset_io);
-
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-ebsa110/Makefile linux/arch/arm/mach-ebsa110/Makefile
--- v2.4.3/linux/arch/arm/mach-ebsa110/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-ebsa110/Makefile	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,23 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET		:= ebsa110.o
+
+# Object file lists.
+
+obj-y			:= arch.o io.o irq.o mm.o time.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
+export-objs		:= io.o
+
+obj-$(CONFIG_LEDS)	+= leds.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-ebsa110/arch.c linux/arch/arm/mach-ebsa110/arch.c
--- v2.4.3/linux/arch/arm/mach-ebsa110/arch.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-ebsa110/arch.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,33 @@
+/*
+ *  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.
+ */
+#include <linux/tty.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+
+#include <asm/elf.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/dec21285.h>
+
+extern void ebsa110_map_io(void);
+extern void ebsa110_init_irq(void);
+
+MACHINE_START(EBSA110, "EBSA110")
+	MAINTAINER("Russell King")
+	BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000)
+	BOOT_PARAMS(0x00000400)
+	DISABLE_PARPORT(0)
+	DISABLE_PARPORT(2)
+	SOFT_REBOOT
+	MAPIO(ebsa110_map_io)
+	INITIRQ(ebsa110_init_irq)
+MACHINE_END
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-ebsa110/io.c linux/arch/arm/mach-ebsa110/io.c
--- v2.4.3/linux/arch/arm/mach-ebsa110/io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-ebsa110/io.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,320 @@
+/*
+ *  linux/arch/arm/mach-ebsa110/isamem.c
+ *
+ *  Copyright (C) 2001 Russell King
+ *
+ * Perform "ISA" memory and IO accesses.  The EBSA110 has some "peculiarities"
+ * in the way it handles accesses to odd IO ports on 16-bit devices.  These
+ * devices have their D0-D15 lines connected to the processors D0-D15 lines.
+ * Since they expect all byte IO operations to be performed on D0-D7, and the
+ * StrongARM expects to transfer the byte to these odd addresses on D8-D15,
+ * we must use a trick to get the required behaviour.
+ *
+ * The trick employed here is to use long word stores to odd address -1.  The
+ * glue logic picks this up as a "trick" access, and asserts the LSB of the
+ * peripherals address bus, thereby accessing the odd IO port.  Meanwhile, the
+ * StrongARM transfers its data on D0-D7 as expected.
+ *
+ * Things get more interesting on the pass-1 EBSA110 - the PCMCIA controller
+ * wiring was screwed in such a way that it had limited memory space access.
+ * Luckily, the work-around for this is not too horrible.  See
+ * __isamem_convert_addr for the details.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/page.h>
+
+static u32 __isamem_convert_addr(void *addr)
+{
+	u32 ret, a = (u32) addr;
+
+	/*
+	 * The PCMCIA controller is wired up as follows:
+	 *        +---------+---------+---------+---------+---------+---------+
+	 * PCMCIA | 2 2 2 2 | 1 1 1 1 | 1 1 1 1 | 1 1     |         |         |
+	 *        | 3 2 1 0 | 9 8 7 6 | 5 4 3 2 | 1 0 9 8 | 7 6 5 4 | 3 2 1 0 |
+	 *        +---------+---------+---------+---------+---------+---------+
+	 *  CPU   | 2 2 2 2 | 2 1 1 1 | 1 1 1 1 | 1 1 1   |         |         |
+	 *        | 4 3 2 1 | 0 9 9 8 | 7 6 5 4 | 3 2 0 9 | 8 7 6 5 | 4 3 2 x |
+	 *        +---------+---------+---------+---------+---------+---------+
+	 *
+	 * This means that we can access PCMCIA regions as follows:
+	 *	0x*10000 -> 0x*1ffff
+	 *	0x*70000 -> 0x*7ffff
+	 *	0x*90000 -> 0x*9ffff
+	 *	0x*f0000 -> 0x*fffff
+	 */
+	ret  = (a & 0xf803fe) << 1;
+	ret |= (a & 0x03fc00) << 2;
+
+	ret += 0xe8000000;
+
+	if ((a & 0x20000) == (a & 0x40000) >> 1)
+		return ret;
+
+	BUG();
+	return 0;
+}
+
+/*
+ * read[bwl] and write[bwl]
+ */
+u8 __readb(void *addr)
+{
+	u32 ret, a = __isamem_convert_addr(addr);
+
+	if ((int)addr & 1)
+		ret = __arch_getl(a);
+	else
+		ret = __arch_getb(a);
+	return ret;
+}
+
+u16 __readw(void *addr)
+{
+	u32 a = __isamem_convert_addr(addr);
+
+	if ((int)addr & 1)
+		BUG();
+
+	return __arch_getw(a);
+}
+
+u32 __readl(void *addr)
+{
+	u32 ret, a = __isamem_convert_addr(addr);
+
+	if ((int)addr & 3)
+		BUG();
+
+	ret = __arch_getw(a);
+	ret |= __arch_getw(a + 4) << 16;
+	return ret;
+}
+
+EXPORT_SYMBOL(__readb);
+EXPORT_SYMBOL(__readw);
+EXPORT_SYMBOL(__readl);
+
+void __writeb(u8 val, void *addr)
+{
+	u32 a = __isamem_convert_addr(addr);
+
+	if ((int)addr & 1)
+		__arch_putl(val, a);
+	else
+		__arch_putb(val, a);
+}
+
+void __writew(u16 val, void *addr)
+{
+	u32 a = __isamem_convert_addr(addr);
+
+	if ((int)addr & 1)
+		BUG();
+
+	__arch_putw(val, a);
+}
+
+void __writel(u32 val, void *addr)
+{
+	u32 a = __isamem_convert_addr(addr);
+
+	if ((int)addr & 3)
+		BUG();
+
+	__arch_putw(val, a);
+	__arch_putw(val >> 16, a + 4);
+}
+
+EXPORT_SYMBOL(__writeb);
+EXPORT_SYMBOL(__writew);
+EXPORT_SYMBOL(__writel);
+
+#define SUPERIO_PORT(p) \
+	(((p) >> 3) == (0x3f8 >> 3) || \
+	 ((p) >> 3) == (0x2f8 >> 3) || \
+	 ((p) >> 3) == (0x378 >> 3))
+
+u8 __inb(int port)
+{
+	u32 ret;
+
+	/*
+	 * The SuperIO registers use sane addressing techniques...
+	 */
+	if (SUPERIO_PORT(port))
+		ret = __arch_getb(ISAIO_BASE + (port << 2));
+	else {
+		u32 a = ISAIO_BASE + ((port & ~1) << 1);
+
+		/*
+		 * Shame nothing else does
+		 */
+		if (port & 1)
+			ret = __arch_getl(a);
+		else
+			ret = __arch_getb(a);
+	}
+	return ret;
+}
+
+u16 __inw(int port)
+{
+	u32 ret;
+
+	/*
+	 * The SuperIO registers use sane addressing techniques...
+	 */
+	if (SUPERIO_PORT(port))
+		ret = __arch_getw(ISAIO_BASE + (port << 2));
+	else {
+		u32 a = ISAIO_BASE + ((port & ~1) << 1);
+
+		/*
+		 * Shame nothing else does
+		 */
+		if (port & 1)
+			BUG();
+
+		ret = __arch_getw(a);
+	}
+	return ret;
+}
+
+u32 __inl(int port)
+{
+	BUG();
+}
+
+EXPORT_SYMBOL(__inb);
+EXPORT_SYMBOL(__inw);
+EXPORT_SYMBOL(__inl);
+
+void __outb(u8 val, int port)
+{
+	/*
+	 * The SuperIO registers use sane addressing techniques...
+	 */
+	if (SUPERIO_PORT(port))
+		__arch_putb(val, ISAIO_BASE + (port << 2));
+	else {
+		u32 a = ISAIO_BASE + ((port & ~1) << 1);
+
+		/*
+		 * Shame nothing else does
+		 */
+		if (port & 1)
+			__arch_putl(val, a);
+		else
+			__arch_putb(val, a);
+	}
+}
+
+void __outw(u16 val, int port)
+{
+	u32 off;
+
+	/*
+	 * The SuperIO registers use sane addressing techniques...
+	 */
+	if (SUPERIO_PORT(port))
+		off = port << 2;
+	else {
+		off = (port & ~1) << 1;
+		if (port & 1)
+			BUG();
+
+	}
+	__arch_putw(val, ISAIO_BASE + off);
+}
+
+void __outl(u32 val, int port)
+{
+	BUG();
+}
+
+EXPORT_SYMBOL(__outb);
+EXPORT_SYMBOL(__outw);
+EXPORT_SYMBOL(__outl);
+
+extern void __arch_writesb(unsigned long virt, const void *from, int len);
+extern void __arch_writesw(unsigned long virt, const void *from, int len);
+extern void __arch_writesl(unsigned long virt, const void *from, int len);
+extern void __arch_readsb(unsigned long virt, void *from, int len);
+extern void __arch_readsw(unsigned long virt, void *from, int len);
+extern void __arch_readsl(unsigned long virt, void *from, int len);
+
+void outsb(unsigned int port, const void *from, int len)
+{
+	u32 off;
+
+	if (SUPERIO_PORT(port))
+		off = port << 2;
+	else {
+		off = (port & ~1) << 1;
+		if (port & 1)
+			BUG();
+	}
+
+	__arch_writesb(ISAIO_BASE + off, from, len);
+}
+
+void insb(unsigned int port, void *from, int len)
+{
+	u32 off;
+
+	if (SUPERIO_PORT(port))
+		off = port << 2;
+	else {
+		off = (port & ~1) << 1;
+		if (port & 1)
+			BUG();
+	}
+
+	__arch_readsb(ISAIO_BASE + off, from, len);
+}
+
+void outsw(unsigned int port, const void *from, int len)
+{
+	u32 off;
+
+	if (SUPERIO_PORT(port))
+		off = port << 2;
+	else {
+		off = (port & ~1) << 1;
+		if (port & 1)
+			BUG();
+	}
+
+	__arch_writesw(ISAIO_BASE + off, from, len);
+}
+
+void insw(unsigned int port, void *from, int len)
+{
+	u32 off;
+
+	if (SUPERIO_PORT(port))
+		off = port << 2;
+	else {
+		off = (port & ~1) << 1;
+		if (port & 1)
+			BUG();
+	}
+
+	__arch_readsw(ISAIO_BASE + off, from, len);
+}
+
+void outsl(unsigned int port, const void *from, int len)
+{
+	panic("outsl not supported on this architecture");
+}
+
+void insl(unsigned int port, void *from, int len)
+{
+	panic("insl not supported on this architecture");
+}
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-ebsa110/irq.c linux/arch/arm/mach-ebsa110/irq.c
--- v2.4.3/linux/arch/arm/mach-ebsa110/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-ebsa110/irq.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,55 @@
+/*
+ *  linux/arch/arm/mach-ebsa110/irq.c
+ *
+ *  Copyright (C) 1996-1998 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
+ * published by the Free Software Foundation.
+ *
+ *  Changelog:
+ *   22-08-1998	RMK	Restructured IRQ routines
+ */
+#include <linux/init.h>
+
+#include <asm/mach/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "hardware.h"
+
+static void ebsa110_mask_irq(unsigned int irq)
+{
+	__raw_writeb(1 << irq, IRQ_MCLR);
+}
+
+static void ebsa110_unmask_irq(unsigned int irq)
+{
+	__raw_writeb(1 << irq, IRQ_MSET);
+}
+ 
+void __init ebsa110_init_irq(void)
+{
+	unsigned long flags;
+	int irq;
+
+	save_flags_cli (flags);
+	__raw_writeb(0xff, IRQ_MCLR);
+	__raw_writeb(0x55, IRQ_MSET);
+	__raw_writeb(0x00, IRQ_MSET);
+	if (__raw_readb(IRQ_MASK) != 0x55)
+		while (1);
+	__raw_writeb(0xff, IRQ_MCLR);	/* clear all interrupt enables */
+	restore_flags (flags);
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= ebsa110_mask_irq;
+		irq_desc[irq].mask	= ebsa110_mask_irq;
+		irq_desc[irq].unmask	= ebsa110_unmask_irq;
+	}
+}
+
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-ebsa110/leds.c linux/arch/arm/mach-ebsa110/leds.c
--- v2.4.3/linux/arch/arm/mach-ebsa110/leds.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-ebsa110/leds.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,51 @@
+/*
+ *  linux/arch/arm/mach-ebsa110/leds.c
+ *
+ *  Copyright (C) 1998 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
+ * published by the Free Software Foundation.
+ *
+ *  EBSA-110 LED control routines.  We use the led as follows:
+ *
+ *   - Red - toggles state every 50 timer interrupts
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+static spinlock_t leds_lock;
+
+static void ebsa110_leds_event(led_event_t ledevt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&leds_lock, flags);
+
+	switch(ledevt) {
+	case led_timer:
+		*(volatile unsigned char *)SOFT_BASE ^= 128;
+		break;
+
+	default:
+		break;
+	}
+
+	spin_unlock_irqrestore(&leds_lock, flags);
+}
+
+static int __init leds_init(void)
+{
+	if (machine_is_ebsa110())
+		leds_event = ebsa110_leds_event;
+
+	return 0;
+}
+
+__initcall(leds_init);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-ebsa110/mm.c linux/arch/arm/mach-ebsa110/mm.c
--- v2.4.3/linux/arch/arm/mach-ebsa110/mm.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-ebsa110/mm.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,43 @@
+/*
+ *  linux/arch/arm/mach-ebsa110/mm.c
+ *
+ *  Copyright (C) 1998-1999 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
+ * published by the Free Software Foundation.
+ *
+ *  Extra MM routines for the EBSA-110 architecture
+ */
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+
+#include "hardware.h"
+ 
+static struct map_desc ebsa110_io_desc[] __initdata = {
+	/*
+	 * sparse external-decode ISAIO space
+	 */
+	{ IRQ_STAT,    TRICK4_PHYS, PGDIR_SIZE,  DOMAIN_IO, 0, 1, 0, 0 }, /* IRQ_STAT/IRQ_MCLR */
+	{ IRQ_MASK,    TRICK3_PHYS, PGDIR_SIZE,  DOMAIN_IO, 0, 1, 0, 0 }, /* IRQ_MASK/IRQ_MSET */
+	{ SOFT_BASE,   TRICK1_PHYS, PGDIR_SIZE,  DOMAIN_IO, 0, 1, 0, 0 }, /* SOFT_BASE */
+	{ PIT_BASE,    TRICK0_PHYS, PGDIR_SIZE,  DOMAIN_IO, 0, 1, 0, 0 }, /* PIT_BASE */
+
+	/*
+	 * self-decode ISAIO space
+	 */
+	{ ISAIO_BASE,  ISAIO_PHYS,  ISAIO_SIZE,  DOMAIN_IO, 0, 1, 0, 0 },
+	{ ISAMEM_BASE, ISAMEM_PHYS, ISAMEM_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
+	LAST_DESC
+};
+
+void __init ebsa110_map_io(void)
+{
+	iotable_init(ebsa110_io_desc);
+}
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-ebsa110/time.c linux/arch/arm/mach-ebsa110/time.c
--- v2.4.3/linux/arch/arm/mach-ebsa110/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-ebsa110/time.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,113 @@
+/*
+ *  linux/arch/arm/mach-ebsa110/time.c
+ *
+ *  Copyright (C) 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
+ * published by the Free Software Foundation.
+ */
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define PIT_CTRL		(PIT_BASE + 0x0d)
+#define PIT_T2			(PIT_BASE + 0x09)
+#define PIT_T1			(PIT_BASE + 0x05)
+#define PIT_T0			(PIT_BASE + 0x01)
+
+/*
+ * This is the rate at which your MCLK signal toggles (in Hz)
+ * This was measured on a 10 digit frequency counter sampling
+ * over 1 second.
+ */
+#define MCLK	47894000
+
+/*
+ * This is the rate at which the PIT timers get clocked
+ */
+#define CLKBY7	(MCLK / 7)
+
+/*
+ * If CLKBY7 is larger than this, then we must do software
+ * division of the timer interrupt.
+ */
+#if CLKBY7 > 6553500
+#define DIVISOR	2
+#else
+#define DIVISOR 1
+#endif
+
+/*
+ * This is the counter value
+ */
+#define COUNT	((CLKBY7 + (DIVISOR * HZ / 2)) / (DIVISOR * HZ))
+
+extern unsigned long (*gettimeoffset)(void);
+
+static unsigned long divisor;
+
+/*
+ * Get the time offset from the system PIT.  Note that if we have missed an
+ * interrupt, then the PIT counter will roll over (ie, be negative).
+ * This actually works out to be convenient.
+ */
+static unsigned long ebsa110_gettimeoffset(void)
+{
+	unsigned long offset, count;
+
+	__raw_writeb(0x40, PIT_CTRL);
+	count = __raw_readb(PIT_T1);
+	count |= __raw_readb(PIT_T1) << 8;
+
+	/*
+	 * If count > COUNT, make the number negative.
+	 */
+	if (count > COUNT)
+		count |= 0xffff0000;
+
+	offset = COUNT * (DIVISOR - divisor);
+	offset -= count;
+
+	/*
+	 * `offset' is in units of timer counts.  Convert
+	 * offset to units of microseconds.
+	 */
+	offset = offset * (1000000 / HZ) / (COUNT * DIVISOR);
+
+	return offset;
+}
+
+int ebsa110_reset_timer(void)
+{
+	u32 count;
+
+	/* latch and read timer 1 */
+	__raw_writeb(0x40, PIT_CTRL);
+	count = __raw_readb(PIT_T1);
+	count |= __raw_readb(PIT_T1) << 8;
+
+	count += COUNT;
+
+	__raw_writeb(count & 0xff, PIT_T1);
+	__raw_writeb(count >> 8, PIT_T1);
+
+	if (divisor == 0)
+		divisor = DIVISOR;
+	divisor -= 1;
+	return divisor;
+}
+
+void __init ebsa110_setup_timer(void)
+{
+	/*
+	 * Timer 1, mode 2, LSB/MSB
+	 */
+	__raw_writeb(0x70, PIT_CTRL);
+	__raw_writeb(COUNT & 0xff, PIT_T1);
+	__raw_writeb(COUNT >> 8, PIT_T1);
+	divisor = DIVISOR - 1;
+
+	gettimeoffset = ebsa110_gettimeoffset;
+}
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-footbridge/Makefile linux/arch/arm/mach-footbridge/Makefile
--- v2.4.3/linux/arch/arm/mach-footbridge/Makefile	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mach-footbridge/Makefile	Thu Apr 12 12:20:31 2001
@@ -5,42 +5,32 @@
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 
+USE_STANDARD_AS_RULE := true
+
 O_TARGET		:= footbridge.o
 
 # Object file lists.
 
-obj-y			:= arch.o #dma.o mm.o
+obj-y			:= arch.o irq.o mm.o #dma.o
 obj-m			:=
 obj-n			:=
 obj-			:=
 
 export-objs		:= netwinder-hw.o
 
-ifeq ($(CONFIG_PCI),y)
-obj-$(CONFIG_ARCH_CATS) += cats-pci.o
-obj-$(CONFIG_ARCH_EBSA285) += ebsa285-pci.o
-obj-$(CONFIG_ARCH_NETWINDER) += netwinder-pci.o
-obj-$(CONFIG_ARCH_PERSONAL_SERVER) += personal-pci.o
-endif
-
-ifeq ($(CONFIG_LEDS),y)
-obj-$(CONFIG_ARCH_CO285) += ebsa285-leds.o
-obj-$(CONFIG_ARCH_EBSA285) += ebsa285-leds.o
-obj-$(CONFIG_ARCH_NETWINDER) += netwinder-leds.o
-endif
+pci-$(CONFIG_ARCH_CATS) += cats-pci.o
+pci-$(CONFIG_ARCH_EBSA285) += ebsa285-pci.o
+pci-$(CONFIG_ARCH_NETWINDER) += netwinder-pci.o
+pci-$(CONFIG_ARCH_PERSONAL_SERVER) += personal-pci.o
+
+leds-$(CONFIG_ARCH_CO285) += ebsa285-leds.o
+leds-$(CONFIG_ARCH_EBSA285) += ebsa285-leds.o
+leds-$(CONFIG_ARCH_NETWINDER) += netwinder-leds.o
 
 obj-$(CONFIG_ARCH_CATS) += cats-hw.o
 obj-$(CONFIG_ARCH_NETWINDER) += netwinder-hw.o
 
-# Files that are both resident and modular; remove from modular.
-
-obj-m		:= $(filter-out $(obj-y), $(obj-m))
-
-# Translate to Rules.make lists.
-
-O_OBJS		:= $(filter-out $(export-objs), $(obj-y))
-OX_OBJS 	:= $(filter	$(export-objs), $(obj-y))
-M_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-m)))
-MX_OBJS 	:= $(sort $(filter     $(export-objs), $(obj-m)))
+obj-$(CONFIG_PCI)	+=$(pci-y)
+obj-$(CONFIG_LEDS)	+=$(leds-y)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-footbridge/arch.c linux/arch/arm/mach-footbridge/arch.c
--- v2.4.3/linux/arch/arm/mach-footbridge/arch.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mach-footbridge/arch.c	Thu Apr 12 12:20:31 2001
@@ -19,9 +19,8 @@
 
 #include <asm/mach/arch.h>
 
-extern void setup_initrd(unsigned int start, unsigned int size);
-extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz);
-extern void __init footbridge_map_io(void);
+extern void footbridge_map_io(void);
+extern void footbridge_init_irq(void);
 
 #ifdef CONFIG_ARCH_EBSA285
 
@@ -42,6 +41,7 @@
 	VIDEO(0x000a0000, 0x000bffff)
 	FIXUP(fixup_ebsa285)
 	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
 MACHINE_END
 #endif
 
@@ -91,6 +91,7 @@
 	DISABLE_PARPORT(2)
 	FIXUP(fixup_netwinder)
 	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
 MACHINE_END
 #endif
 
@@ -111,9 +112,11 @@
 MACHINE_START(CATS, "Chalice-CATS")
 	MAINTAINER("Philip Blundell")
 	BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
+	BOOT_PARAMS(0x00000100)
 	SOFT_REBOOT
 	FIXUP(fixup_cats)
 	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
 MACHINE_END
 #endif
 
@@ -139,6 +142,7 @@
 	BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0x7cf00000)
 	FIXUP(fixup_coebsa285)
 	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
 MACHINE_END
 #endif
 
@@ -148,5 +152,6 @@
 	BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
 	BOOT_PARAMS(0x00000100)
 	MAPIO(footbridge_map_io)
+	INITIRQ(footbridge_init_irq)
 MACHINE_END
 #endif
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-footbridge/irq.c linux/arch/arm/mach-footbridge/irq.c
--- v2.4.3/linux/arch/arm/mach-footbridge/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-footbridge/irq.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,223 @@
+/*
+ *  linux/arch/arm/mach-footbridge/irq.c
+ *
+ *  Copyright (C) 1996-2000 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
+ * published by the Free Software Foundation.
+ *
+ *  Changelog:
+ *   22-Aug-1998 RMK	Restructured IRQ routines
+ *   03-Sep-1998 PJB	Merged CATS support
+ *   20-Jan-1998 RMK	Started merge of EBSA286, CATS and NetWinder
+ *   26-Jan-1999 PJB	Don't use IACK on CATS
+ *   16-Mar-1999 RMK	Added autodetect of ISA PICs
+ */
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/dec21285.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+/*
+ * Footbridge IRQ translation table
+ *  Converts from our IRQ numbers into FootBridge masks
+ */
+static const int fb_irq_mask[] = {
+	IRQ_MASK_UART_RX,	/*  0 */
+	IRQ_MASK_UART_TX,	/*  1 */
+	IRQ_MASK_TIMER1,	/*  2 */
+	IRQ_MASK_TIMER2,	/*  3 */
+	IRQ_MASK_TIMER3,	/*  4 */
+	IRQ_MASK_IN0,		/*  5 */
+	IRQ_MASK_IN1,		/*  6 */
+	IRQ_MASK_IN2,		/*  7 */
+	IRQ_MASK_IN3,		/*  8 */
+	IRQ_MASK_DOORBELLHOST,	/*  9 */
+	IRQ_MASK_DMA1,		/* 10 */
+	IRQ_MASK_DMA2,		/* 11 */
+	IRQ_MASK_PCI,		/* 12 */
+	IRQ_MASK_SDRAMPARITY,	/* 13 */
+	IRQ_MASK_I2OINPOST,	/* 14 */
+	IRQ_MASK_PCI_ABORT,	/* 15 */
+	IRQ_MASK_PCI_SERR,	/* 16 */
+	IRQ_MASK_DISCARD_TIMER,	/* 17 */
+	IRQ_MASK_PCI_DPERR,	/* 18 */
+	IRQ_MASK_PCI_PERR,	/* 19 */
+};
+
+static void fb_mask_irq(unsigned int irq)
+{
+	*CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(irq)];
+}
+
+static void fb_unmask_irq(unsigned int irq)
+{
+	*CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(irq)];
+}
+
+static void __init __fb_init_irq(void)
+{
+	int irq;
+
+	/*
+	 * setup DC21285 IRQs
+	 */
+	*CSR_IRQ_DISABLE = -1;
+	*CSR_FIQ_DISABLE = -1;
+
+	for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) {
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= fb_mask_irq;
+		irq_desc[irq].mask	= fb_mask_irq;
+		irq_desc[irq].unmask	= fb_unmask_irq;
+	}
+}
+
+extern int isa_irq;
+
+static void isa_mask_pic_lo_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
+}
+
+static void isa_mask_ack_pic_lo_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
+	outb(0x20, PIC_LO);
+}
+
+static void isa_unmask_pic_lo_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
+}
+
+static void isa_mask_pic_hi_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
+}
+
+static void isa_mask_ack_pic_hi_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
+	outb(0x62, PIC_LO);
+	outb(0x20, PIC_HI);
+}
+
+static void isa_unmask_pic_hi_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
+}
+
+static void no_action(int irq, void *dev_id, struct pt_regs *regs)
+{
+}
+
+static struct irqaction irq_cascade = { handler: no_action, name: "cascade", };
+static struct resource pic1_resource = { "pic1", 0x20, 0x3f };
+static struct resource pic2_resource = { "pic2", 0xa0, 0xbf };
+
+static void __init isa_init_irq(int irq)
+{
+	/*
+	 * Setup, and then probe for an ISA PIC
+	 * If the PIC is not there, then we
+	 * ignore the PIC.
+	 */
+	outb(0x11, PIC_LO);
+	outb(_ISA_IRQ(0), PIC_MASK_LO);	/* IRQ number		*/
+	outb(0x04, PIC_MASK_LO);	/* Slave on Ch2		*/
+	outb(0x01, PIC_MASK_LO);	/* x86			*/
+	outb(0xf5, PIC_MASK_LO);	/* pattern: 11110101	*/
+
+	outb(0x11, PIC_HI);
+	outb(_ISA_IRQ(8), PIC_MASK_HI);	/* IRQ number		*/
+	outb(0x02, PIC_MASK_HI);	/* Slave on Ch1		*/
+	outb(0x01, PIC_MASK_HI);	/* x86			*/
+	outb(0xfa, PIC_MASK_HI);	/* pattern: 11111010	*/
+
+	outb(0x0b, PIC_LO);
+	outb(0x0b, PIC_HI);
+
+	if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) {
+		outb(0xff, PIC_MASK_LO);/* mask all IRQs	*/
+		outb(0xff, PIC_MASK_HI);/* mask all IRQs	*/
+		isa_irq = irq;
+	} else
+		isa_irq = -1;
+
+	if (isa_irq != -1) {
+		for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
+			irq_desc[irq].valid	= 1;
+			irq_desc[irq].probe_ok	= 1;
+			irq_desc[irq].mask_ack	= isa_mask_ack_pic_lo_irq;
+			irq_desc[irq].mask	= isa_mask_pic_lo_irq;
+			irq_desc[irq].unmask	= isa_unmask_pic_lo_irq;
+		}
+
+		for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
+			irq_desc[irq].valid	= 1;
+			irq_desc[irq].probe_ok	= 1;
+			irq_desc[irq].mask_ack	= isa_mask_ack_pic_hi_irq;
+			irq_desc[irq].mask	= isa_mask_pic_hi_irq;
+			irq_desc[irq].unmask	= isa_unmask_pic_hi_irq;
+		}
+
+		request_resource(&ioport_resource, &pic1_resource);
+		request_resource(&ioport_resource, &pic2_resource);
+		setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade);
+		setup_arm_irq(isa_irq, &irq_cascade);
+
+		/*
+		 * On the NetWinder, don't automatically
+		 * enable ISA IRQ11 when it is requested.
+		 * There appears to be a missing pull-up
+		 * resistor on this line.
+		 */
+		if (machine_is_netwinder())
+			irq_desc[_ISA_IRQ(11)].noautoenable = 1;
+	}
+}
+
+void __init footbridge_init_irq(void)
+{
+	__fb_init_irq();
+
+	if (!footbridge_cfn_mode())
+		return;
+
+	if (machine_is_ebsa285())
+		/* The following is dependent on which slot
+		 * you plug the Southbridge card into.  We
+		 * currently assume that you plug it into
+		 * the right-hand most slot.
+		 */
+		isa_init_irq(IRQ_PCI);
+
+	if (machine_is_cats())
+		isa_init_irq(IRQ_IN2);
+
+	if (machine_is_netwinder())
+		isa_init_irq(IRQ_IN3);
+}
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-footbridge/mm.c linux/arch/arm/mach-footbridge/mm.c
--- v2.4.3/linux/arch/arm/mach-footbridge/mm.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-footbridge/mm.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,117 @@
+/*
+ *  linux/arch/arm/mach-footbridge/mm.c
+ *
+ *  Copyright (C) 1998-2000 Russell King, Dave Gilbert.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ *  Extra MM routines for the EBSA285 architecture
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+ 
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/hardware/dec21285.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/map.h>
+
+/*
+ * Common mapping for all systems.  Note that the outbound write flush is
+ * commented out since there is a "No Fix" problem with it.  Not mapping
+ * it means that we have extra bullet protection on our feet.
+ */
+static struct map_desc fb_common_io_desc[] __initdata = {
+ { ARMCSR_BASE,	 DC21285_ARMCSR_BASE,	    ARMCSR_SIZE,  DOMAIN_IO, 0, 1, 0, 0 },
+ { XBUS_BASE,    0x40000000,		    XBUS_SIZE,    DOMAIN_IO, 0, 1, 0, 0 },
+ LAST_DESC
+};
+
+/*
+ * The mapping when the footbridge is in host mode.  We don't map any of
+ * this when we are in add-in mode.
+ */
+static struct map_desc ebsa285_host_io_desc[] __initdata = {
+#if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_FOOTBRIDGE_HOST)
+ { PCIMEM_BASE,  DC21285_PCI_MEM,	    PCIMEM_SIZE,  DOMAIN_IO, 0, 1, 0, 0 },
+ { PCICFG0_BASE, DC21285_PCI_TYPE_0_CONFIG, PCICFG0_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
+ { PCICFG1_BASE, DC21285_PCI_TYPE_1_CONFIG, PCICFG1_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
+ { PCIIACK_BASE, DC21285_PCI_IACK,	    PCIIACK_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
+ { PCIO_BASE,    DC21285_PCI_IO,	    PCIO_SIZE,	  DOMAIN_IO, 0, 1, 0, 0 },
+#endif
+ LAST_DESC
+};
+
+/*
+ * The CO-ebsa285 mapping.
+ */
+static struct map_desc co285_io_desc[] __initdata = {
+#ifdef CONFIG_ARCH_CO285
+ { PCIO_BASE,	 DC21285_PCI_IO,	    PCIO_SIZE,    DOMAIN_IO, 0, 1, 0, 0 },
+ { PCIMEM_BASE,	 DC21285_PCI_MEM,	    PCIMEM_SIZE,  DOMAIN_IO, 0, 1, 0, 0 },
+#endif
+ LAST_DESC
+};
+
+void __init footbridge_map_io(void)
+{
+	struct map_desc *desc = NULL;
+
+	/*
+	 * Set up the common mapping first; we need this to
+	 * determine whether we're in host mode or not.
+	 */
+	iotable_init(fb_common_io_desc);
+
+	/*
+	 * Now, work out what we've got to map in addition on this
+	 * platform.
+	 */
+	if (machine_is_co285())
+		desc = co285_io_desc;
+	else if (footbridge_cfn_mode())
+		desc = ebsa285_host_io_desc;
+
+	if (desc)
+		iotable_init(desc);
+}
+
+#ifdef CONFIG_FOOTBRIDGE_ADDIN
+
+/*
+ * These two functions convert virtual addresses to PCI addresses and PCI
+ * addresses to virtual addresses.  Note that it is only legal to use these
+ * on memory obtained via get_free_page or kmalloc.
+ */
+unsigned long __virt_to_bus(unsigned long res)
+{
+#ifdef CONFIG_DEBUG_ERRORS
+	if (res < PAGE_OFFSET || res >= (unsigned long)high_memory) {
+		printk("__virt_to_bus: invalid virtual address 0x%08lx\n", res);
+		__backtrace();
+	}
+#endif
+	return (res - PAGE_OFFSET) + (*CSR_PCISDRAMBASE & 0xfffffff0);
+}
+
+unsigned long __bus_to_virt(unsigned long res)
+{
+	res -= (*CSR_PCISDRAMBASE & 0xfffffff0);
+	res += PAGE_OFFSET;
+
+#ifdef CONFIG_DEBUG_ERRORS
+	if (res < PAGE_OFFSET || res >= (unsigned long)high_memory) {
+		printk("__bus_to_virt: invalid virtual address 0x%08lx\n", res);
+		__backtrace();
+	}
+#endif
+	return res;
+}
+
+#endif
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-sa1100/Makefile linux/arch/arm/mach-sa1100/Makefile
--- v2.4.3/linux/arch/arm/mach-sa1100/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/mach-sa1100/Makefile	Thu Apr 12 12:20:31 2001
@@ -11,13 +11,14 @@
 
 # Object file lists.
 
-obj-y			:= arch.o hw.o #dma.o mm.o
+obj-y			:= arch.o hw.o dma-sa1100.o # mm.o
 obj-m			:=
 obj-n			:=
 obj-			:=
 
-export-objs		:= hw.o leds.o
+export-objs		:= dma-sa1100.o dma-sa1111.o hw.o leds.o
 
 obj-$(CONFIG_LEDS)	+= leds.o
+obj-$(CONFIG_SA1111)	+= dma-sa1111.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-sa1100/arch.c linux/arch/arm/mach-sa1100/arch.c
--- v2.4.3/linux/arch/arm/mach-sa1100/arch.c	Fri Mar  2 11:12:06 2001
+++ linux/arch/arm/mach-sa1100/arch.c	Thu Apr 12 12:20:31 2001
@@ -19,8 +19,23 @@
 
 #include <asm/mach/arch.h>
 
-extern void setup_initrd(unsigned int start, unsigned int size);
-extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz);
+extern void genarch_init_irq(void);
+
+
+static void sa1100_power_off(void)
+{
+	mdelay(100);
+	cli();
+	/* disable internal oscillator, float CS lines */
+	PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
+	/* set lowest clock */
+	PPCR = 0;
+	/* set all GPIOs to input mode */
+	GPDR = 0;
+	/* enter sleep mode */
+	PMCR = PMCR_SF;
+}
+
 
 static void victor_power_off(void)
 {
@@ -47,10 +62,13 @@
 	mi->bank[__nr].start = (__start), \
 	mi->bank[__nr].size = (__size), \
 	mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
+
 static void __init
 fixup_sa1100(struct machine_desc *desc, struct param_struct *params,
 	     char **cmdline, struct meminfo *mi)
 {
+	pm_power_off = sa1100_power_off;
+
 	if (machine_is_assabet()) {
 		/* 
 		 * On Assabet, we must probe for the Neponset board *before*
@@ -82,6 +100,16 @@
 		setup_initrd( 0xc0800000, 3*1024*1024 );
 	}
 
+	else if (machine_is_pangolin()) {
+		SET_BANK( 0, 0xc0000000, 32*1024*1024 );
+		SET_BANK( 1, 0xc8000000, 32*1024*1024 );
+		mi->nr_banks = 2;
+		
+		ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+		setup_ramdisk( 1, 0, 0, 16384 );
+		setup_initrd( 0xc0800000, 9*1024*1024 );
+	}
+
 	else if (machine_is_brutus()) {
 		SET_BANK( 0, 0xc0000000, 4*1024*1024 );
 		SET_BANK( 1, 0xc8000000, 4*1024*1024 );
@@ -133,7 +161,7 @@
 		setup_initrd(0xc0400000, 4*1024*1024);
 	}
 
-	else if (machine_is_thinclient() || machine_is_graphicsclient()) {
+	else if (machine_is_graphicsclient()) {
 		SET_BANK( 0, 0xc0000000, 16*1024*1024 );
 		mi->nr_banks = 1;
 
@@ -154,15 +182,6 @@
 		if( *((char*)0xc0000100) )
 			*cmdline = ((char *)0xc0000100);
 	}
-	else if (machine_is_tifon()) {
-		SET_BANK( 0, 0xc0000000, 16*1024*1024 );
-		SET_BANK( 1, 0xc8000000, 16*1024*1024 );
-		mi->nr_banks = 2;
-
-		ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0);
-		setup_ramdisk(1, 0, 0, 4096);
-		setup_initrd( 0xd0000000 + 0x1100004, 0x140000 );
-	}
 
 	else if (machine_is_victor()) {
 		SET_BANK( 0, 0xc0000000, 4*1024*1024 );
@@ -180,6 +199,16 @@
 		pm_power_off = victor_power_off;
 	}
 
+        else if (machine_is_sherman()) {
+                SET_BANK( 0, 0xc0000000, 64*1024*1024 );
+                SET_BANK( 1, 0xc8000000, 64*1024*1024 );
+                mi->nr_banks = 2;
+
+                ROOT_DEV = MKDEV( 60, 2 );
+                setup_ramdisk( 1, 0, 0, 8192 );
+//              setup_initrd( 0xc0400000, 8*1024*1024 );
+}
+
 	else if (machine_is_xp860()) {
 		SET_BANK( 0, 0xc0000000, 32*1024*1024 );
 		mi->nr_banks = 1;
@@ -193,6 +222,15 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
+MACHINE_END
+#endif
+#ifdef CONFIG_SA1100_PANGOLIN
+MACHINE_START(PANGOLIN, "Dialogue-Pangolin")
+	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+	FIXUP(fixup_sa1100)
+	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_BITSY
@@ -201,6 +239,7 @@
 	BOOT_PARAMS(0xc0000100)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_BRUTUS
@@ -208,6 +247,7 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_CERF
@@ -216,6 +256,7 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_EMPEG
@@ -223,6 +264,7 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
@@ -230,14 +272,16 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_ITSY
 MACHINE_START(ITSY, "Compaq Itsy")
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
-	BOOT_PARAMS(0xc0000100
+	BOOT_PARAMS(0xc0000100)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_LART
@@ -245,6 +289,7 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_NANOENGINE
@@ -252,6 +297,7 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_PLEB
@@ -259,20 +305,7 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
-MACHINE_END
-#endif
-#ifdef CONFIG_SA1100_THINCLIENT
-MACHINE_START(THINCLIENT, "ADS ThinClient")
-	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
-	FIXUP(fixup_sa1100)
-	MAPIO(sa1100_map_io)
-MACHINE_END
-#endif
-#ifdef CONFIG_SA1100_TIFON
-MACHINE_START(TIFON, "Tifon")
-	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
-	FIXUP(fixup_sa1100)
-	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_VICTOR
@@ -280,6 +313,15 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
+MACHINE_END
+#endif
+#ifdef CONFIG_SA1100_SHERMAN
+MACHINE_START(SHERMAN, "Blazie Engineering Sherman")
+        BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+        FIXUP(fixup_sa1100)
+        MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
 #ifdef CONFIG_SA1100_XP860
@@ -287,5 +329,6 @@
 	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
 	FIXUP(fixup_sa1100)
 	MAPIO(sa1100_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
 #endif
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-sa1100/dma-sa1100.c linux/arch/arm/mach-sa1100/dma-sa1100.c
--- v2.4.3/linux/arch/arm/mach-sa1100/dma-sa1100.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-sa1100/dma-sa1100.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,538 @@
+/*
+ * arch/arm/kernel/dma-sa1100.c
+ *
+ * Support functions for the SA11x0 internal DMA channels.
+ * (see also Documentation/arm/SA1100/DMA)
+ *
+ * Copyright (C) 2000 Nicolas Pitre
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/mach/dma.h>
+
+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTK( s, arg... )  printk( "dma<%s>: " s, dma->device_id , ##arg )
+#else
+#define DPRINTK( x... )
+#endif
+
+
+/*
+ * Maximum physical DMA buffer size
+ */
+#define MAX_DMA_SIZE		0x1fff
+#define MAX_DMA_ORDER		12
+
+
+/*
+ * DMA control register structure
+ */
+typedef struct {
+	volatile u_long DDAR;
+	volatile u_long SetDCSR;
+	volatile u_long ClrDCSR;
+	volatile u_long RdDCSR;
+	volatile dma_addr_t DBSA;
+	volatile u_long DBTA;
+	volatile dma_addr_t DBSB;
+	volatile u_long DBTB;
+} dma_regs_t;
+
+
+/*
+ * DMA buffer structure
+ */
+struct dma_buf_s {
+	int size;		/* buffer size */
+	dma_addr_t dma_start;	/* starting DMA address */
+	dma_addr_t dma_ptr;	/* current DMA pointer position */
+	int ref;		/* number of DMA references */
+	void *id;		/* to identify buffer from outside */
+	struct dma_buf_s *next;	/* next buffer to process */
+};
+
+
+#include "dma.h"
+
+sa1100_dma_t dma_chan[MAX_SA1100_DMA_CHANNELS];
+
+
+/*
+ * DMA processing...
+ */
+
+static inline int start_sa1100_dma(sa1100_dma_t * dma, dma_addr_t dma_ptr, int size)
+{
+	dma_regs_t *regs = dma->regs;
+	int status;
+	int use_bufa;
+
+	status = regs->RdDCSR;
+
+	/* If both DMA buffers are started, there's nothing else we can do. */
+	if ((status & DCSR_STRTA) && (status & DCSR_STRTB)) {
+		DPRINTK("start: st %#x busy\n", status);
+		return -EBUSY;
+	}
+
+	use_bufa = (((status & DCSR_BIU) && (status & DCSR_STRTB)) ||
+		    (!(status & DCSR_BIU) && !(status & DCSR_STRTA)));
+	if (use_bufa) {
+		regs->ClrDCSR = DCSR_DONEA | DCSR_STRTA;
+		regs->DBSA = dma_ptr;
+		regs->DBTA = size;
+		regs->SetDCSR = DCSR_STRTA | DCSR_IE | DCSR_RUN;
+		DPRINTK("start a=%#x s=%d on A\n", dma_ptr, size);
+	} else {
+		regs->ClrDCSR = DCSR_DONEB | DCSR_STRTB;
+		regs->DBSB = dma_ptr;
+		regs->DBTB = size;
+		regs->SetDCSR = DCSR_STRTB | DCSR_IE | DCSR_RUN;
+		DPRINTK("start a=%#x s=%d on B\n", dma_ptr, size);
+	}
+
+	return 0;
+}
+
+
+static int start_dma(sa1100_dma_t *dma, dma_addr_t dma_ptr, int size)
+{
+	if (channel_is_sa1111_sac(dma - dma_chan))
+		return start_sa1111_sac_dma(dma, dma_ptr, size);
+	return start_sa1100_dma(dma, dma_ptr, size);
+}
+
+
+/* This must be called with IRQ disabled */
+static void process_dma(sa1100_dma_t * dma)
+{
+	dma_buf_t *buf;
+	int chunksize;
+
+	for (;;) {
+		buf = dma->tail;
+
+		if (!buf) {
+			/* no more data available */
+			DPRINTK("process: no more buf (dma %s)\n",
+				dma->curr ? "active" : "inactive");
+			/*
+			 * Some devices may require DMA still sending data
+			 * at any time for clock reference, etc.
+			 * Note: if there is still a data buffer being
+			 * processed then the ref count is negative.  This
+			 * allows for the DMA termination to be accounted in
+			 * the proper order.
+			 */
+			if (dma->spin_size && dma->spin_ref >= 0) {
+				chunksize = dma->spin_size;
+				if (chunksize > MAX_DMA_SIZE)
+					chunksize = (1 << MAX_DMA_ORDER);
+				while (start_dma(dma, dma->spin_addr, chunksize) == 0)
+					dma->spin_ref++;
+				if (dma->curr != NULL)
+					dma->spin_ref = -dma->spin_ref;
+			}
+			break;
+		}
+
+		/*
+		 * Let's try to start DMA on the current buffer.
+		 * If DMA is busy then we break here.
+		 */
+		chunksize = buf->size;
+		if (chunksize > MAX_DMA_SIZE)
+			chunksize = (1 << MAX_DMA_ORDER);
+		DPRINTK("process: b=%#x s=%d\n", (int) buf->id, buf->size);
+		if (start_dma(dma, buf->dma_ptr, chunksize) != 0)
+			break;
+		dma->active = 1;
+		if (!dma->curr)
+			dma->curr = buf;
+		buf->ref++;
+		buf->dma_ptr += chunksize;
+		buf->size -= chunksize;
+		if (buf->size == 0) {
+			/* current buffer is done: move tail to the next one */
+			dma->tail = buf->next;
+			DPRINTK("process: next b=%#x\n", (int) dma->tail);
+		}
+	}
+}
+
+
+/* This must be called with IRQ disabled */
+void sa1100_dma_done (sa1100_dma_t *dma)
+{
+	dma_buf_t *buf = dma->curr;
+
+	if (dma->spin_ref > 0) {
+		dma->spin_ref--;
+	} else if (buf) {
+		buf->ref--;
+		if (buf->ref == 0 && buf->size == 0) {
+			/*
+			 * Current buffer is done.
+			 * Move current reference to the next one and send
+			 * the processed buffer to the callback function,
+			 * then discard it.
+			 */
+			DPRINTK("IRQ: buf done\n");
+			dma->curr = buf->next;
+			if (dma->curr == NULL)
+				dma->spin_ref = -dma->spin_ref;
+			if (dma->head == buf)
+				dma->head = NULL;
+			buf->size = buf->dma_ptr - buf->dma_start;
+			if (dma->callback)
+				dma->callback(buf->id, buf->size);
+			kfree(buf);
+		}
+	}
+
+	process_dma(dma);
+}
+
+
+static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	sa1100_dma_t *dma = (sa1100_dma_t *) dev_id;
+	int status = dma->regs->RdDCSR;
+
+	DPRINTK("IRQ: b=%#x st=%#x\n", (int) dma->curr->id, status);
+
+	dma->regs->ClrDCSR = DCSR_ERROR | DCSR_DONEA | DCSR_DONEB;
+	if (!(status & (DCSR_DONEA | DCSR_DONEB)))
+		return;
+
+	sa1100_dma_done (dma);
+}
+
+
+/*
+ * DMA interface functions
+ */
+
+/*
+ * Get dma list
+ * for /proc/dma
+ */
+int sa1100_get_dma_list(char *buf)
+{
+	int i, len = 0;
+
+	for (i = 0; i < MAX_SA1100_DMA_CHANNELS; i++) {
+		if (dma_chan[i].lock)
+			len += sprintf(buf + len, "%2d: %s\n",
+				       i, dma_chan[i].device_id);
+	}
+	return len;
+}
+
+int sa1100_request_dma(dmach_t * channel, const char *device_id)
+{
+	sa1100_dma_t *dma = NULL;
+	dma_regs_t *regs;
+	int ch, err;
+
+	*channel = -1;		/* to be sure we catch the freeing of a misregistered channel */
+
+	for (ch = 0; ch < SA1100_DMA_CHANNELS; ch++) {
+		dma = &dma_chan[ch];
+		if (xchg(&dma->lock, 1) == 0)
+			break;
+	}
+	if (ch >= SA1100_DMA_CHANNELS) {
+		printk(KERN_ERR "%s: no free DMA channel available\n",
+		       device_id);
+		return -EBUSY;
+	}
+
+	err = request_irq(dma->irq, dma_irq_handler, SA_INTERRUPT,
+			  device_id, (void *) dma);
+	if (err) {
+		printk(KERN_ERR
+		       "%s: unable to request IRQ %d for DMA channel %d\n",
+		       device_id, dma->irq, ch);
+		dma->lock = 0;
+		return err;
+	}
+
+	*channel = ch;
+	dma->device_id = device_id;
+	dma->callback = NULL;
+	dma->spin_size = 0;
+
+	regs = dma->regs;
+	regs->ClrDCSR =
+	    (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
+	     DCSR_IE | DCSR_ERROR | DCSR_RUN);
+	regs->DDAR = 0;
+
+	DPRINTK("requested\n");
+	return 0;
+}
+
+
+int sa1100_dma_set_callback(dmach_t channel, dma_callback_t cb)
+{
+	sa1100_dma_t *dma = &dma_chan[channel];
+
+	dma->callback = cb;
+	DPRINTK("cb = %p\n", cb);
+	return 0;
+}
+
+
+int sa1100_dma_set_device(dmach_t channel, dma_device_t device)
+{
+	sa1100_dma_t *dma = &dma_chan[channel];
+	dma_regs_t *regs = dma->regs;
+
+	if (dma->ready)
+		return -EINVAL;
+
+	regs->ClrDCSR = DCSR_STRTA | DCSR_STRTB | DCSR_IE | DCSR_RUN;
+	regs->DDAR = device;
+	DPRINTK("DDAR = %#x\n", device);
+	dma->ready = 1;
+	return 0;
+}
+
+
+int sa1100_dma_set_spin(dmach_t channel, dma_addr_t addr, int size)
+{
+	sa1100_dma_t *dma = &dma_chan[channel];
+	int flags;
+
+	if (channel >= SA1100_DMA_CHANNELS)
+		return -EINVAL;
+
+	DPRINTK("set spin %d at %#x\n", size, addr);
+	local_irq_save(flags);
+	dma->spin_addr = addr;
+	dma->spin_size = size;
+	if (size)
+		process_dma(dma);
+	local_irq_restore(flags);
+	return 0;
+}
+
+
+int sa1100_dma_queue_buffer(dmach_t channel, void *buf_id,
+			    dma_addr_t data, int size)
+{
+	sa1100_dma_t *dma;
+	dma_buf_t *buf;
+	int flags;
+
+	dma = &dma_chan[channel];
+	if (!dma->ready)
+		return -EINVAL;
+
+	buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
+
+	buf->next = NULL;
+	buf->ref = 0;
+	buf->dma_ptr = buf->dma_start = data;
+	buf->size = size;
+	buf->id = buf_id;
+	DPRINTK("queueing b=%#x a=%#x s=%d\n", (int) buf_id, data, size);
+
+	local_irq_save(flags);
+	if (dma->head)
+		dma->head->next = buf;
+	dma->head = buf;
+	if (!dma->tail)
+		dma->tail = buf;
+	process_dma(dma);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+int sa1100_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr)
+{
+	sa1100_dma_t *dma = &dma_chan[channel];
+	dma_regs_t *regs = dma->regs;
+	int flags, ret;
+
+	if (channel_is_sa1111_sac(channel))
+		return sa1111_dma_get_current(channel, buf_id, addr);
+
+	local_irq_save(flags);
+	if (dma->curr && dma->spin_ref <= 0) {
+		dma_buf_t *buf = dma->curr;
+		int status, using_bufa;
+
+		status = regs->RdDCSR;
+		/*
+		 * If we got here, that's because there is, or recently was, a
+		 * buffer being processed.  We must determine whether buffer
+		 * A or B is active.  Two possibilities: either we are
+		 * in the middle of a buffer, or the DMA controller just
+		 * switched to the next toggle but the interrupt hasn't been
+		 * serviced yet.  The former case is straight forward.  In
+		 * the later case, we'll do like if DMA is just at the end
+		 * of the previous toggle since all registers haven't been
+		 * reset yet.  This goes around the edge case and since we're
+		 * always a little behind anyways it shouldn't make a big
+		 * difference.  If DMA has been stopped prior calling this
+		 * then the position is always exact.
+		 */
+		using_bufa = ((!(status & DCSR_BIU) &&  (status & DCSR_STRTA)) ||
+			      ( (status & DCSR_BIU) && !(status & DCSR_STRTB)));
+		if (buf_id)
+			*buf_id = buf->id;
+		*addr = (using_bufa) ? regs->DBSA : regs->DBSB;
+		/*
+		 * Clamp funky pointers sometimes returned by the hardware
+		 * on completed DMA transfers
+		 */
+		if (*addr < buf->dma_start ||
+		    *addr > buf->dma_ptr)
+			*addr = buf->dma_ptr;
+		DPRINTK("curr_pos: b=%#x a=%#x\n", (int)dma->curr->id, *addr);
+		ret = 0;
+	} else {
+		if (buf_id)
+			*buf_id = NULL;
+		*addr = 0;
+		DPRINTK("curr_pos: spinning\n");
+		ret = -ENXIO;
+	}
+	local_irq_restore(flags);
+	return ret;
+}
+
+
+int sa1100_dma_stop(dmach_t channel)
+{
+	sa1100_dma_t *dma = &dma_chan[channel];
+	dma_regs_t *regs = dma->regs;
+
+	if (channel_is_sa1111_sac(channel))
+		return sa1111_dma_stop(channel);
+
+	regs->ClrDCSR = DCSR_RUN | DCSR_IE;
+	return 0;
+}
+
+
+int sa1100_dma_resume(dmach_t channel)
+{
+	sa1100_dma_t *dma = &dma_chan[channel];
+	dma_regs_t *regs = dma->regs;
+
+	if (channel_is_sa1111_sac(channel))
+		return sa1111_dma_resume(channel);
+
+	regs->SetDCSR = DCSR_RUN | DCSR_IE;
+	return 0;
+}
+
+
+int sa1100_dma_flush_all(dmach_t channel)
+{
+	sa1100_dma_t *dma;
+	dma_buf_t *buf, *next_buf;
+	int flags;
+
+	dma = &dma_chan[channel];
+	local_irq_save(flags);
+	if (channel_is_sa1111_sac(channel))
+		sa1111_reset_sac_dma(channel);
+	else
+		dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB|DCSR_RUN|DCSR_IE;
+	buf = dma->curr;
+	if (!buf)
+		buf = dma->tail;
+	dma->head = dma->tail = dma->curr = NULL;
+	dma->active = 0;
+	dma->spin_ref = 0;
+	if (dma->spin_size)
+		process_dma(dma);
+	local_irq_restore(flags);
+	while (buf) {
+		next_buf = buf->next;
+		kfree(buf);
+		buf = next_buf;
+	}
+	DPRINTK("flushed\n");
+	return 0;
+}
+
+
+void sa1100_free_dma(dmach_t channel)
+{
+	sa1100_dma_t *dma;
+
+	if ((unsigned) channel >= MAX_SA1100_DMA_CHANNELS)
+		return;
+
+	dma = &dma_chan[channel];
+	if (!dma->lock) {
+		printk(KERN_ERR "Trying to free free DMA%d\n", channel);
+		return;
+	}
+
+	sa1100_dma_set_spin(channel, 0, 0);
+	sa1100_dma_flush_all(channel);
+	dma->ready = 0;
+
+	if (channel_is_sa1111_sac(channel)) {
+		sa1111_cleanup_sac_dma(channel);
+	} else {
+		free_irq(IRQ_DMA0 + channel, (void *) dma);
+	}
+	dma->lock = 0;
+
+	DPRINTK("freed\n");
+}
+
+
+EXPORT_SYMBOL(sa1100_request_dma);
+EXPORT_SYMBOL(sa1100_dma_set_callback);
+EXPORT_SYMBOL(sa1100_dma_set_device);
+EXPORT_SYMBOL(sa1100_dma_set_spin);
+EXPORT_SYMBOL(sa1100_dma_queue_buffer);
+EXPORT_SYMBOL(sa1100_dma_get_current);
+EXPORT_SYMBOL(sa1100_dma_stop);
+EXPORT_SYMBOL(sa1100_dma_resume);
+EXPORT_SYMBOL(sa1100_dma_flush_all);
+EXPORT_SYMBOL(sa1100_free_dma);
+
+
+static int __init sa1100_init_dma(void)
+{
+	int channel;
+	for (channel = 0; channel < SA1100_DMA_CHANNELS; channel++) {
+		dma_chan[channel].regs =
+		    (dma_regs_t *) io_p2v(_DDAR(channel));
+		dma_chan[channel].irq = IRQ_DMA0 + channel;
+	}
+	return 0;
+}
+
+__initcall(sa1100_init_dma);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-sa1100/dma-sa1111.c linux/arch/arm/mach-sa1100/dma-sa1111.c
--- v2.4.3/linux/arch/arm/mach-sa1100/dma-sa1111.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-sa1100/dma-sa1111.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,346 @@
+/*
+ *  linux/arch/arm/mach-sa1100/dma-sa1111.c
+ *
+ *  Copyright (C) 2000 John Dorsey
+ *
+ *  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
+ *  published by the Free Software Foundation.
+ *
+ *  4 September 2000 - created.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+
+// #define DEBUG
+#ifdef DEBUG
+#define DPRINTK( s, arg... )  printk( "dma<%s>: " s, dma->device_id , ##arg )
+#else
+#define DPRINTK( x... )
+#endif
+
+
+/*
+ * Control register structure for the SA1111 SAC DMA
+ */
+
+typedef struct {
+	volatile u_long SAD_CS;
+	volatile dma_addr_t SAD_SA;
+	volatile u_long SAD_CA;
+	volatile dma_addr_t SAD_SB;
+	volatile u_long SAD_CB;
+} dma_regs_t;
+
+#include "dma.h"
+
+
+void sa1111_reset_sac_dma(dmach_t channel)
+{
+	sa1100_dma_t *dma = &dma_chan[channel];
+	dma->regs->SAD_CS = 0;
+	mdelay(1);
+	dma->dma_a = dma->dma_b = 0;
+}
+
+
+int start_sa1111_sac_dma(sa1100_dma_t *dma, dma_addr_t dma_ptr, size_t size)
+{
+  	dma_regs_t *sac_regs = dma->regs;
+
+	DPRINTK(" SAC DMA %cCS %02x at %08x (%d)\n",
+		(sac_regs==&SADTCS)?'T':'R', sac_regs->SAD_CS, dma_ptr, size);
+
+	/* The minimum transfer length requirement has not yet been
+	 * verified:
+	 */
+	if( size < SA1111_SAC_DMA_MIN_XFER )
+	  printk(KERN_WARNING "Warning: SAC xfers below %u bytes may be buggy!"
+		 " (%u bytes)\n", SA1111_SAC_DMA_MIN_XFER, size);
+
+	if( dma->dma_a && dma->dma_b ){
+	  	DPRINTK("  neither engine available! (A %d, B %d)\n",
+			dma->dma_a, dma->dma_b);
+	  	return -1;
+	}
+
+	if( sa1111_check_dma_bug(dma_ptr) )
+	  	printk(KERN_WARNING "Warning: DMA address %08x is buggy!\n",
+		       dma_ptr);
+
+	if( (dma->last_dma || dma->dma_b) && dma->dma_a == 0 ){
+	  	if( sac_regs->SAD_CS & SAD_CS_DBDB ){
+		  	DPRINTK("  awaiting \"done B\" interrupt, not starting\n");
+			return -1;
+		}
+		sac_regs->SAD_SA = SA1111_DMA_ADDR((u_int)dma_ptr);
+		sac_regs->SAD_CA = size;
+		sac_regs->SAD_CS = SAD_CS_DSTA | SAD_CS_DEN;
+		++dma->dma_a;
+		DPRINTK("  with A [%02lx %08lx %04lx]\n", sac_regs->SAD_CS,
+			sac_regs->SAD_SA, sac_regs->SAD_CA);
+	} else {
+	  	if( sac_regs->SAD_CS & SAD_CS_DBDA ){
+		  	DPRINTK("  awaiting \"done A\" interrupt, not starting\n");
+			return -1;
+		}
+		sac_regs->SAD_SB = SA1111_DMA_ADDR((u_int)dma_ptr);
+		sac_regs->SAD_CB = size;
+		sac_regs->SAD_CS = SAD_CS_DSTB | SAD_CS_DEN;
+		++dma->dma_b;
+		DPRINTK("  with B [%02lx %08lx %04lx]\n", sac_regs->SAD_CS,
+			sac_regs->SAD_SB, sac_regs->SAD_CB);
+	}
+
+	/* Additional delay to avoid DMA engine lockup during record: */
+	if( sac_regs == (dma_regs_t*)&SADRCS )
+	  	mdelay(1);	/* NP : wouuuh! ugly... */
+
+	return 0;
+}
+
+
+static void sa1111_sac_dma_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+  	sa1100_dma_t *dma = (sa1100_dma_t *) dev_id;
+
+	DPRINTK("irq %d, last DMA serviced was %c, CS %02x\n", irq,
+		dma->last_dma?'B':'A', dma->regs->SAD_CS);
+
+	/* Occasionally, one of the DMA engines (A or B) will
+	 * lock up. We try to deal with this by quietly kicking
+	 * the control register for the afflicted transfer
+	 * direction.
+	 *
+	 * Note for the debugging-inclined: we currently aren't
+	 * properly flushing the DMA engines during channel
+	 * shutdown. A slight hiccup at the beginning of playback
+	 * after a channel has been stopped can be heard as
+	 * evidence of this. Programmatically, this shows up
+	 * as either a locked engine, or a spurious interrupt. -jd
+	 */
+
+	if(irq==AUDXMTDMADONEA || irq==AUDRCVDMADONEA){
+
+	  	if(dma->last_dma == 0){
+		  	DPRINTK("DMA B has locked up!\n");
+			dma->regs->SAD_CS = 0;
+			mdelay(1);
+			dma->dma_a = dma->dma_b = 0;
+		} else {
+		  	if(dma->dma_a == 0)
+			  	DPRINTK("spurious SAC IRQ %d\n", irq);
+			else {
+			  	--dma->dma_a;
+
+				/* Servicing the SAC DMA engines too quickly
+				 * after they issue a DONE interrupt causes
+				 * them to lock up.
+				 */
+				if(irq==AUDRCVDMADONEA || irq==AUDRCVDMADONEB)
+				  	mdelay(1);
+			}
+		}
+
+		dma->regs->SAD_CS = SAD_CS_DBDA | SAD_CS_DEN; /* w1c */
+		dma->last_dma = 0;
+
+	} else {
+
+	  	if(dma->last_dma == 1){
+		  	DPRINTK("DMA A has locked up!\n");
+			dma->regs->SAD_CS = 0;
+			mdelay(1);
+			dma->dma_a = dma->dma_b = 0;
+		} else {
+		  	if(dma->dma_b == 0)
+			  	DPRINTK("spurious SAC IRQ %d\n", irq);
+			else {
+			  	--dma->dma_b;
+
+				/* See lock-up note above. */
+				if(irq==AUDRCVDMADONEA || irq==AUDRCVDMADONEB)
+				  	mdelay(1);
+			}
+		}
+
+		dma->regs->SAD_CS = SAD_CS_DBDB | SAD_CS_DEN; /* w1c */
+		dma->last_dma = 1;
+
+	}
+
+	/* NP: maybe this shouldn't be called in all cases? */
+	sa1100_dma_done (dma);
+}
+
+
+int sa1111_sac_request_dma(dmach_t *channel, const char *device_id,
+			   unsigned int direction)
+{
+	sa1100_dma_t *dma = NULL;
+	int ch, irq, err;
+
+	*channel = -1;		/* to be sure we catch the freeing of a misregistered channel */
+
+	ch = SA1111_SAC_DMA_BASE + direction;
+
+	if (!channel_is_sa1111_sac(ch)) {
+	  	printk(KERN_ERR "%s: invalid SA-1111 SAC DMA channel (%d)\n",
+		       device_id, ch);
+		return -1;
+	}
+
+	dma = &dma_chan[ch];
+
+	if (xchg(&dma->lock, 1) == 1) {
+	  	printk(KERN_ERR "%s: SA-1111 SAC DMA channel %d in use\n",
+		       device_id, ch);
+		return -EBUSY;
+	}
+
+	irq = AUDXMTDMADONEA + direction;
+	err = request_irq(irq, sa1111_sac_dma_irq, SA_INTERRUPT,
+			  device_id, (void *) dma);
+	if (err) {
+		printk(KERN_ERR
+		       "%s: unable to request IRQ %d for DMA channel %d (A)\n",
+		       device_id, irq, ch);
+		dma->lock = 0;
+		return err;
+	}
+
+	irq = AUDXMTDMADONEB + direction;
+	err = request_irq(irq, sa1111_sac_dma_irq, SA_INTERRUPT,
+			  device_id, (void *) dma);
+	if (err) {
+		printk(KERN_ERR
+		       "%s: unable to request IRQ %d for DMA channel %d (B)\n",
+		       device_id, irq, ch);
+		dma->lock = 0;
+		return err;
+	}
+
+	*channel = ch;
+	dma->device_id = device_id;
+	dma->callback = NULL;
+	dma->spin_size = 0;
+	dma->ready = 1;
+
+	return 0;
+}
+
+
+/* FIXME:  need to complete the three following functions */
+
+int sa1111_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr)
+{
+	return -ENOSYS;
+}
+
+int sa1111_dma_stop(dmach_t channel)
+{
+	return 0;
+}
+
+int sa1111_dma_resume(dmach_t channel)
+{
+	return 0;
+}
+
+
+void sa1111_cleanup_sac_dma(dmach_t channel)
+{
+	sa1100_dma_t *dma = &dma_chan[channel];
+	free_irq(AUDXMTDMADONEA + (channel - SA1111_SAC_DMA_BASE), (void*) dma);
+	free_irq(AUDXMTDMADONEB + (channel - SA1111_SAC_DMA_BASE), (void*) dma);
+}
+
+
+/* According to the "Intel StrongARM SA-1111 Microprocessor Companion
+ * Chip Specification Update" (June 2000), errata #7, there is a
+ * significant bug in Serial Audio Controller DMA. If the SAC is
+ * accessing a region of memory above 1MB relative to the bank base,
+ * it is important that address bit 10 _NOT_ be asserted. Depending
+ * on the configuration of the RAM, bit 10 may correspond to one
+ * of several different (processor-relative) address bits.
+ *
+ * This routine only identifies whether or not a given DMA address
+ * is susceptible to the bug.
+ */
+int sa1111_check_dma_bug(dma_addr_t addr){
+	unsigned int physaddr=SA1111_DMA_ADDR((unsigned int)addr);
+
+	/* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
+	 * User's Guide" mentions that jumpers R51 and R52 control the
+	 * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
+	 * SDRAM bank 1 on Neponset). The default configuration selects
+	 * Assabet, so any address in bank 1 is necessarily invalid.
+	 */
+	if(machine_is_assabet() && addr >= _DRAMBnk1)
+	  	return -1;
+
+	/* The bug only applies to buffers located more than one megabyte
+	 * above the start of the target bank:
+	 */
+	if(physaddr<(1<<20))
+	  	return 0;
+
+	switch(FExtr(SMCR, SMCR_DRAC)){
+	case 01: /* 10 row + bank address bits, A<20> must not be set */
+	  	if(physaddr & (1<<20))
+		  	return -1;
+		break;
+	case 02: /* 11 row + bank address bits, A<23> must not be set */
+	  	if(physaddr & (1<<23))
+		  	return -1;
+		break;
+	case 03: /* 12 row + bank address bits, A<24> must not be set */
+	  	if(physaddr & (1<<24))
+		  	return -1;
+		break;
+	case 04: /* 13 row + bank address bits, A<25> must not be set */
+	  	if(physaddr & (1<<25))
+		  	return -1;
+		break;
+	case 05: /* 14 row + bank address bits, A<20> must not be set */
+	  	if(physaddr & (1<<20))
+		  	return -1;
+		break;
+	case 06: /* 15 row + bank address bits, A<20> must not be set */
+	  	if(physaddr & (1<<20))
+		  	return -1;
+		break;
+	default:
+	  	printk(KERN_ERR "%s(): invalid SMCR DRAC value 0%o\n",
+		       __FUNCTION__, FExtr(SMCR, SMCR_DRAC));
+		return -1;
+	}
+
+	return 0;
+}
+
+
+EXPORT_SYMBOL(sa1111_sac_request_dma);
+EXPORT_SYMBOL(sa1111_check_dma_bug);
+
+
+static void __init sa1111_init_sac_dma(void)
+{
+	int channel = SA1111_SAC_DMA_BASE;
+	dma_chan[channel++].regs = (dma_regs_t *) &SADTCS;
+	dma_chan[channel++].regs = (dma_regs_t *) &SADRCS;
+}
+
+__initcall(sa1111_init_sac_dma);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-sa1100/dma.h linux/arch/arm/mach-sa1100/dma.h
--- v2.4.3/linux/arch/arm/mach-sa1100/dma.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-sa1100/dma.h	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,56 @@
+/*
+ * Definitions shared between dma-sa1100.c and dma-sa1111.c
+ * (C) 2000 Nicolas Pitre <nico@cam.org>
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+
+
+/*
+ * DMA channel structure.
+ */
+
+typedef struct dma_buf_s dma_buf_t;
+
+typedef struct {
+	unsigned int lock;      /* Device is allocated */
+	const char *device_id;  /* Device name */
+	dma_buf_t *head;        /* where to insert buffers */
+	dma_buf_t *tail;        /* where to remove buffers */
+	dma_buf_t *curr;        /* buffer currently DMA'ed */
+	int ready;              /* 1 if DMA can occur */
+	int active;             /* 1 if DMA is actually processing data */
+	dma_regs_t *regs;       /* points to appropriate DMA registers */
+	int irq;                /* IRQ used by the channel */
+	dma_callback_t callback;        /* ... to call when buffers are done */
+	int spin_size;          /* > 0 when DMA should spin when no more buffer */
+	dma_addr_t spin_addr;   /* DMA address to spin onto */
+	int spin_ref;           /* number of spinning references */
+#ifdef CONFIG_SA1111
+	int dma_a, dma_b, last_dma;	/* SA-1111 specific */
+#endif
+} sa1100_dma_t;
+
+extern sa1100_dma_t dma_chan[MAX_SA1100_DMA_CHANNELS];
+
+
+int start_sa1111_sac_dma(sa1100_dma_t *dma, dma_addr_t dma_ptr, size_t size);
+int sa1111_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr);
+int sa1111_dma_stop(dmach_t channel);
+int sa1111_dma_resume(dmach_t channel);
+void sa1111_reset_sac_dma(dmach_t channel);
+void sa1111_cleanup_sac_dma(dmach_t channel);
+
+void sa1100_dma_done (sa1100_dma_t *dma);
+
+
+#ifdef CONFIG_SA1111
+#define channel_is_sa1111_sac(ch) \
+	((ch) >= SA1111_SAC_DMA_BASE && \
+	 (ch) <  SA1111_SAC_DMA_BASE + SA1111_SAC_DMA_CHANNELS)
+#else
+#define channel_is_sa1111_sac(ch) (0)
+#endif
+
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-shark/Makefile linux/arch/arm/mach-shark/Makefile
--- v2.4.3/linux/arch/arm/mach-shark/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/mach-shark/Makefile	Thu Apr 12 12:20:31 2001
@@ -18,6 +18,6 @@
 
 export-objs		:= 
 
-#obj-$(CONFIG_LEDS)	+= leds.o
+obj-$(CONFIG_LEDS)	+= leds.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-shark/arch.c linux/arch/arm/mach-shark/arch.c
--- v2.4.3/linux/arch/arm/mach-shark/arch.c	Tue Sep 19 08:31:53 2000
+++ linux/arch/arm/mach-shark/arch.c	Thu Apr 12 12:20:31 2001
@@ -18,14 +18,31 @@
 
 #include <asm/mach/arch.h>
 
-extern void setup_initrd(unsigned int start, unsigned int size);
-extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz);
-extern void __init footbridge_map_io(void);
-extern void __init shark_map_io(void);
+static void __init
+fixup_shark(struct machine_desc *desc, struct param_struct *params,
+	char **cmdline, struct meminfo *mi) {
+	int i;
+
+	mi->nr_banks=0;
+	for (i=0;i<NR_BANKS;i++) {
+		if (params->u1.s.pages_in_bank[i] != 0) {
+			mi->nr_banks++;
+			mi->bank[i].node  = 0;
+			mi->bank[i].start = params->u1.s.pages_in_bank[i] & 0xffff0000;
+			mi->bank[i].size  = (params->u1.s.pages_in_bank[i] & 0xffff)*PAGE_SIZE;
+			params->u1.s.pages_in_bank[i] &= 0xffff;
+		}
+	}
+}
+
+extern void shark_map_io(void);
+extern void genarch_init_irq(void);
 
 MACHINE_START(SHARK, "Shark")
 	MAINTAINER("Alexander Schulz")
 	BOOT_MEM(0x08000000, 0x40000000, 0xe0000000)
-	VIDEO(0x06000000, 0x061fffff)
+	BOOT_PARAMS(0x08003000)
+	FIXUP(fixup_shark)
 	MAPIO(shark_map_io)
+	INITIRQ(genarch_init_irq)
 MACHINE_END
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-shark/dma.c linux/arch/arm/mach-shark/dma.c
--- v2.4.3/linux/arch/arm/mach-shark/dma.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mach-shark/dma.c	Thu Apr 12 12:20:31 2001
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/mach-shark/dma.c
  *
- *  by Alexander.Schulz@stud.uni-karlsruhe.de
+ *  by Alexander Schulz <aschulz@netwinder.org>
  *
  *  derived from:
  *  arch/arm/kernel/dma-ebsa285.c
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-shark/leds.c linux/arch/arm/mach-shark/leds.c
--- v2.4.3/linux/arch/arm/mach-shark/leds.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-shark/leds.c	Thu Apr 12 12:20:31 2001
@@ -0,0 +1,163 @@
+/*
+ * arch/arm/kernel/leds-shark.c
+ * by Alexander Schulz <aschulz@netwinder.org>
+ *
+ * derived from:
+ * arch/arm/kernel/leds-footbridge.c
+ * Copyright (C) 1998-1999 Russell King
+ *
+ * DIGITAL Shark LED control routines.
+ *
+ * The leds use is as follows:
+ *  - Green front - toggles state every 50 timer interrupts
+ *  - Amber front - Unused, this is a dual color led (Amber/Green)
+ *  - Amber back  - On if system is not idle
+ *
+ * Changelog:
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+static char led_state;
+static short hw_led_state;
+static short saved_state;
+
+static spinlock_t leds_lock = SPIN_LOCK_UNLOCKED;
+
+short sequoia_read(int addr) {
+  outw(addr,0x24);
+  return inw(0x26);
+}
+
+void sequoia_write(short value,short addr) {
+  outw(addr,0x24);
+  outw(value,0x26);
+}
+
+static void sequoia_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&leds_lock, flags);
+
+	hw_led_state = sequoia_read(0x09);
+
+	switch (evt) {
+	case led_start:
+		hw_led_state |= SEQUOIA_LED_GREEN;
+		hw_led_state |= SEQUOIA_LED_AMBER;
+#ifdef CONFIG_LEDS_CPU
+		hw_led_state |= SEQUOIA_LED_BACK;
+#else
+		hw_led_state &= ~SEQUOIA_LED_BACK;
+#endif
+		led_state |= LED_STATE_ENABLED;
+		break;
+
+	case led_stop:
+		hw_led_state &= ~SEQUOIA_LED_BACK;
+		hw_led_state |= SEQUOIA_LED_GREEN;
+		hw_led_state |= SEQUOIA_LED_AMBER;
+		led_state &= ~LED_STATE_ENABLED;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		saved_state = hw_led_state;
+		hw_led_state &= ~SEQUOIA_LED_BACK;
+		hw_led_state |= SEQUOIA_LED_GREEN;
+		hw_led_state |= SEQUOIA_LED_AMBER;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = saved_state;
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= SEQUOIA_LED_GREEN;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~SEQUOIA_LED_BACK;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= SEQUOIA_LED_BACK;
+		break;
+#endif
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~SEQUOIA_LED_GREEN;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= SEQUOIA_LED_GREEN;
+		break;
+
+	case led_amber_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~SEQUOIA_LED_AMBER;
+		break;
+
+	case led_amber_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= SEQUOIA_LED_AMBER;
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= SEQUOIA_LED_BACK;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~SEQUOIA_LED_BACK;
+		break;
+
+	default:
+		break;
+	}
+
+	if  (led_state & LED_STATE_ENABLED)
+		sequoia_write(hw_led_state,0x09);
+
+	spin_unlock_irqrestore(&leds_lock, flags);
+}
+
+static int __init leds_init(void)
+{
+	extern void (*leds_event)(led_event_t);
+	short temp;
+	
+	leds_event = sequoia_leds_event;
+
+	/* Make LEDs independent of power-state */
+	request_region(0x24,4,"sequoia");
+	temp = sequoia_read(0x09);
+	temp |= 1<<10;
+	sequoia_write(temp,0x09);
+	leds_event(led_start);
+	return 0;
+}
+
+__initcall(leds_init);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mach-shark/mm.c linux/arch/arm/mach-shark/mm.c
--- v2.4.3/linux/arch/arm/mach-shark/mm.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mach-shark/mm.c	Thu Apr 12 12:20:31 2001
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/mach-shark/mm.c
  *
- *  by Alexander.Schulz@stud.uni-karlsruhe.de
+ *  by Alexander Schulz <aschulz@netwinder.org>
  *
  * 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
@@ -19,8 +19,6 @@
 
 static struct map_desc shark_io_desc[] __initdata = {
 	{ IO_BASE	, IO_START	, IO_SIZE	, DOMAIN_IO, 0, 1, 0, 0 },
-	{ FB_BASE	, FB_START	, FB_SIZE	, DOMAIN_IO, 0, 1, 0, 0 },
-	{ FBREG_BASE	, FBREG_START	, FBREG_SIZE	, DOMAIN_IO, 0, 1, 0, 0 },
 	LAST_DESC
 };
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/Makefile linux/arch/arm/mm/Makefile
--- v2.4.3/linux/arch/arm/mm/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/mm/Makefile	Thu Apr 12 12:20:31 2001
@@ -13,13 +13,22 @@
 
 # Object file lists.
 
-obj-y		:= extable.o fault-common.o fault-$(PROCESSOR).o init.o \
-		   mm-$(PROCESSOR).o small_page.o
+obj-y		:= init.o
 obj-m		:=
 obj-n		:=
 obj-		:=
 export-objs	:= proc-syms.o
 
+cpu32-y		:= consistent.o fault-armv.o ioremap.o mm-armv.o
+cpu32-$(CONFIG_MODULES) += proc-syms.o
+
+obj-y		+= extable.o fault-common.o
+obj-$(CONFIG_CPU_26) += fault-armo.o mm-armo.o small_page.o
+obj-$(CONFIG_CPU_32) += $(cpu32-y)
+
+obj-$(CONFIG_DISCONTIGMEM) += discontig.o
+
+# Select the processor-specific files
 p-$(CONFIG_CPU_26)	+= proc-arm2,3.o
 p-$(CONFIG_CPU_ARM610)	+= proc-arm6,7.o
 p-$(CONFIG_CPU_ARM710)	+= proc-arm6,7.o
@@ -29,11 +38,6 @@
 p-$(CONFIG_CPU_SA110)	+= proc-sa110.o
 p-$(CONFIG_CPU_SA1100)	+= proc-sa110.o
 
-obj-$(CONFIG_CPU_32)  	+= consistent.o ioremap.o
-ifeq ($(CONFIG_CPU_32),y)
-obj-$(CONFIG_MODULES)	+= proc-syms.o
-endif
-
 # Integrator follows "new style"
 # Soon, others will do too, and we can get rid of this
 MMMACH		:= mm-$(MACHINE).c
@@ -46,10 +50,4 @@
 include $(TOPDIR)/Rules.make
 
 # Special dependencies
-proc-arm2,3.o:	../lib/constants.h
-proc-arm6,7.o:	../lib/constants.h
-proc-arm720.o:	../lib/constants.h
-proc-arm920.o:	../lib/constants.h
-proc-arm10.o:	../lib/constants.h
-proc-sa110.o:	../lib/constants.h
-
+$(p-y):	$(TOPDIR)/include/asm-arm/constants.h
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/consistent.c linux/arch/arm/mm/consistent.c
--- v2.4.3/linux/arch/arm/mm/consistent.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/consistent.c	Thu Apr 12 12:20:31 2001
@@ -34,9 +34,9 @@
  */
 void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
 {
-	int order;
-	unsigned long page;
-	void *ret;
+	struct page *page, *end, *free;
+	unsigned long order;
+	void *ret, *virt;
 
 	if (in_interrupt())
 		BUG();
@@ -44,37 +44,47 @@
 	size = PAGE_ALIGN(size);
 	order = get_order(size);
 
-	page = __get_free_pages(gfp, order);
+	page = alloc_pages(gfp, order);
 	if (!page)
 		goto no_page;
 
-	ret = __ioremap(virt_to_phys((void *)page), size, 0);
-	if (ret) {
-		/* free wasted pages */
-		unsigned long end;
-
-		/*
-		 * we need to ensure that there are no
-		 * cachelines in use, or worse dirty in
-		 * this area.
-		 */
-		invalidate_dcache_range(page, page + size);
-		invalidate_dcache_range((unsigned long)ret, (unsigned long)ret + size);
-
-		*dma_handle = __virt_to_bus(page);
-
-		end = page + (PAGE_SIZE << order);
-		page += size;
-		while (page < end) {
-			free_page(page);
-			page += PAGE_SIZE;
-		}
-		return ret;
+	/*
+	 * We could do with a page_to_phys and page_to_bus here.
+	 */
+	virt = page_address(page);
+	*dma_handle = virt_to_bus(virt);
+	ret = __ioremap(virt_to_phys(virt), size, 0);
+	if (!ret)
+		goto no_remap;
+
+#if 0 /* ioremap_does_flush_cache_all */
+	/*
+	 * we need to ensure that there are no cachelines in use, or
+	 * worse dirty in this area.  Really, we don't need to do
+	 * this since __ioremap does a flush_cache_all() anyway. --rmk
+	 */
+	invalidate_dcache_range(virt, virt + size);
+#endif
+
+	/*
+	 * free wasted pages.  We skip the first page since
+	 * we know that it will have count = 1 and won't
+	 * require freeing.
+	 */
+	page = virt_to_page(virt);
+	free = page + (size >> PAGE_SHIFT);
+	end  = page + (1 << order);
+
+	while (++page < end) {
+		set_page_count(page, 1);
+		if (page >= free)
+			__free_page(page);
 	}
+	return ret;
 
-	free_pages(page, order);
+no_remap:
+	__free_pages(page, order);
 no_page:
-	BUG();
 	return NULL;
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.4.3/linux/arch/arm/mm/fault-armv.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/mm/fault-armv.c	Thu Apr 12 12:20:31 2001
@@ -2,7 +2,7 @@
  *  linux/arch/arm/mm/fault-armv.c
  *
  *  Copyright (C) 1995  Linus Torvalds
- *  Modifications for ARM processor (c) 1995-1999 Russell King
+ *  Modifications for ARM processor (c) 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
@@ -29,7 +29,13 @@
 
 extern void die_if_kernel(const char *str, struct pt_regs *regs, int err);
 extern void show_pte(struct mm_struct *mm, unsigned long addr);
-extern int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs);
+extern int do_page_fault(unsigned long addr, int error_code,
+			 struct pt_regs *regs);
+extern int do_translation_fault(unsigned long addr, int error_code,
+				struct pt_regs *regs);
+extern void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
+			unsigned long addr, int error_code,
+			struct pt_regs *regs);
 
 #ifdef CONFIG_ALIGNMENT_TRAP
 /*
@@ -37,12 +43,11 @@
  * /proc/sys/debug/alignment, modified and integrated into
  * Linux 2.1 by Russell King
  *
+ * 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.
- *
- * IMHO, I don't think that the trap handler is advantageous on ARM6,7
- * processors (they'll run like an ARM3).  We'll see.
  */
 #define CODING_BITS(i)	(i & 0x0e000000)
 
@@ -115,91 +120,323 @@
 __initcall(alignment_init);
 #endif /* CONFIG_SYSCTL */
 
+union offset_union {
+	unsigned long un;
+	  signed long sn;
+};
+
+#define TYPE_ERROR	0
+#define TYPE_FAULT	1
+#define TYPE_LDST	2
+#define TYPE_DONE	3
+
+#define get8_unaligned_check(val,addr,err)		\
+	__asm__(					\
+	"1:	ldrb	%1, [%2]\n"			\
+	"2:\n"						\
+	"	.section .fixup,\"ax\"\n"		\
+	"	.align	2\n"				\
+	"3:	mov	%0, #1\n"			\
+	"	b	2b\n"				\
+	"	.previous\n"				\
+	"	.section __ex_table,\"a\"\n"		\
+	"	.align	3\n"				\
+	"	.long	1b, 3b\n"			\
+	"	.previous\n"				\
+	: "=r" (err), "=&r" (val), "=r" (addr)		\
+	: "0" (err), "2" (addr))
+
+#define get8t_unaligned_check(val,addr,err)		\
+	__asm__(					\
+	"1:	ldrbt	%1, [%2]\n"			\
+	"2:\n"						\
+	"	.section .fixup,\"ax\"\n"		\
+	"	.align	2\n"				\
+	"3:	mov	%0, #1\n"			\
+	"	b	2b\n"				\
+	"	.previous\n"				\
+	"	.section __ex_table,\"a\"\n"		\
+	"	.align	3\n"				\
+	"	.long	1b, 3b\n"			\
+	"	.previous\n"				\
+	: "=r" (err), "=&r" (val), "=r" (addr)		\
+	: "0" (err), "2" (addr))
+
+#define get16_unaligned_check(val,addr)				\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		get8_unaligned_check(val,a,err);		\
+		get8_unaligned_check(v,a,err);			\
+		val |= v << 8;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define put16_unaligned_check(val,addr)				\
+	do {							\
+		unsigned int err = 0, v = val, a = addr;	\
+		__asm__(					\
+		"1:	strb	%1, [%2], #1\n"			\
+		"	mov	%1, %1, lsr #8\n"		\
+		"2:	strb	%1, [%2]\n"			\
+		"3:\n"						\
+		"	.section .fixup,\"ax\"\n"		\
+		"	.align	2\n"				\
+		"4:	mov	%0, #1\n"			\
+		"	b	3b\n"				\
+		"	.previous\n"				\
+		"	.section __ex_table,\"a\"\n"		\
+		"	.align	3\n"				\
+		"	.long	1b, 4b\n"			\
+		"	.long	2b, 4b\n"			\
+		"	.previous\n"				\
+		: "=r" (err), "=&r" (v), "=&r" (a)		\
+		: "0" (err), "1" (v), "2" (a));			\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define __put32_unaligned_check(ins,val,addr)			\
+	do {							\
+		unsigned int err = 0, v = val, a = addr;	\
+		__asm__(					\
+		"1:	"ins"	%1, [%2], #1\n"			\
+		"	mov	%1, %1, lsr #8\n"		\
+		"2:	"ins"	%1, [%2], #1\n"			\
+		"	mov	%1, %1, lsr #8\n"		\
+		"3:	"ins"	%1, [%2], #1\n"			\
+		"	mov	%1, %1, lsr #8\n"		\
+		"4:	"ins"	%1, [%2]\n"			\
+		"5:\n"						\
+		"	.section .fixup,\"ax\"\n"		\
+		"	.align	2\n"				\
+		"6:	mov	%0, #1\n"			\
+		"	b	5b\n"				\
+		"	.previous\n"				\
+		"	.section __ex_table,\"a\"\n"		\
+		"	.align	3\n"				\
+		"	.long	1b, 6b\n"			\
+		"	.long	2b, 6b\n"			\
+		"	.long	3b, 6b\n"			\
+		"	.long	4b, 6b\n"			\
+		"	.previous\n"				\
+		: "=r" (err), "=&r" (v), "=&r" (a)		\
+		: "0" (err), "1" (v), "2" (a));			\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define get32_unaligned_check(val,addr)				\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		get8_unaligned_check(val,a,err);		\
+		get8_unaligned_check(v,a,err);			\
+		val |= v << 8;					\
+		get8_unaligned_check(v,a,err);			\
+		val |= v << 16;					\
+		get8_unaligned_check(v,a,err);			\
+		val |= v << 24;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define put32_unaligned_check(val,addr)	 \
+	__put32_unaligned_check("strb", val, addr)
+
+#define get32t_unaligned_check(val,addr)			\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		get8t_unaligned_check(val,a,err);		\
+		get8t_unaligned_check(v,a,err);			\
+		val |= v << 8;					\
+		get8t_unaligned_check(v,a,err);			\
+		val |= v << 16;					\
+		get8t_unaligned_check(v,a,err);			\
+		val |= v << 24;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define put32t_unaligned_check(val,addr) \
+	__put32_unaligned_check("strbt", val, addr)
+
+static void
+do_alignment_finish_ldst(unsigned long addr, unsigned long instr, struct pt_regs *regs, union offset_union offset)
+{
+	if (!LDST_U_BIT(instr))
+		offset.un = -offset.un;
+
+	if (!LDST_P_BIT(instr))
+		addr += offset.un;
+
+	if (!LDST_P_BIT(instr) || LDST_W_BIT(instr))
+		regs->uregs[RN_BITS(instr)] = addr;
+}
+
 static int
-do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
+do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs)
 {
-	unsigned int instr, rd, rn, correction, nr_regs, regbits;
-	unsigned long eaddr;
-	union { unsigned long un; signed long sn; } offset;
+	unsigned int rd = RD_BITS(instr);
 
-	if (user_mode(regs)) {
-		set_cr(cr_no_alignment);
-		ai_user += 1;
-		return 0;
-	}
+	if ((instr & 0x01f00ff0) == 0x01000090)
+		goto swp;
 
-	ai_sys += 1;
+	if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0)
+		goto bad;
+
+	ai_half += 1;
+
+	if (LDST_L_BIT(instr)) {
+		unsigned long val;
+		get16_unaligned_check(val, addr);
+
+		/* signed half-word? */
+		if (instr & 0x40)
+			val = (signed long)((signed short) val);
+
+		regs->uregs[rd] = val;
+	} else
+		put16_unaligned_check(regs->uregs[rd], addr);
+
+	return TYPE_LDST;
+
+swp:
+	printk(KERN_ERR "Alignment trap: not handling swp instruction\n");
+bad:
+	return TYPE_ERROR;
+
+fault:
+	return TYPE_FAULT;
+}
+
+static int
+do_alignment_ldrstr(unsigned long addr, unsigned long instr, struct pt_regs *regs)
+{
+	unsigned int rd = RD_BITS(instr);
+
+	ai_word += 1;
+
+	if (!LDST_P_BIT(instr) && LDST_W_BIT(instr))
+		goto trans;
+
+	if (LDST_L_BIT(instr))
+		get32_unaligned_check(regs->uregs[rd], addr);
+	else
+		put32_unaligned_check(regs->uregs[rd], addr);
+	return TYPE_LDST;
+
+trans:
+	if (LDST_L_BIT(instr))
+		get32t_unaligned_check(regs->uregs[rd], addr);
+	else
+		put32t_unaligned_check(regs->uregs[rd], addr);
+	return TYPE_LDST;
+
+fault:
+	return TYPE_FAULT;
+}
+
+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;
 
-	instr = *(unsigned long *)instruction_pointer(regs);
 	correction = 4; /* sometimes 8 on ARMv3 */
-	regs->ARM_pc += correction + 4;
+	regs->ARM_pc += correction;
 
 	rd = RD_BITS(instr);
 	rn = RN_BITS(instr);
 	eaddr = regs->uregs[rn];
 
-	switch(CODING_BITS(instr)) {
-	case 0x00000000:
-		if ((instr & 0x0ff00ff0) == 0x01000090) {
-			ai_skipped += 1;
-			printk(KERN_ERR "Unaligned trap: not handling swp instruction\n");
-			return 1;
-		}
+	if (LDM_S_BIT(instr))
+		goto bad;
 
-		if (((instr & 0x0e000090) == 0x00000090) && (instr & 0x60) != 0) {
-			ai_half += 1;
-			if (LDSTH_I_BIT(instr))
-				offset.un = (instr & 0xf00) >> 4 | (instr & 15);
-			else
-				offset.un = regs->uregs[RM_BITS(instr)];
-
-			if (LDST_P_BIT(instr)) {
-				if (LDST_U_BIT(instr))
-					eaddr += offset.un;
-				else
-					eaddr -= offset.un;
-			}
+	ai_multi += 1;
+
+	for (regbits = REGMASK_BITS(instr), nr_regs = 0; regbits; regbits >>= 1)
+		nr_regs += 4;
 
-			/*
-			 * This is a "hint" - we already have eaddr worked out by the
-			 * processor for us.
-			 */
-			if (addr != eaddr)
-				printk(KERN_ERR "LDRHSTRH: PC = %08lx, instr = %08x, "
-					"addr = %08lx, eaddr = %08lx\n",
-					 instruction_pointer(regs), instr, addr, eaddr);
-
-			if (LDST_L_BIT(instr))
-				regs->uregs[rd] = get_unaligned((unsigned short *)eaddr);
-			else
-				put_unaligned(regs->uregs[rd], (unsigned short *)eaddr);
-
-			/* signed half-word? */
-			if (instr & 0x40)
-				regs->uregs[rd] = (long)((short) regs->uregs[rd]);
-
-			if (!LDST_P_BIT(instr)) {
-				if (LDST_U_BIT(instr))
-					eaddr += offset.un;
-				else
-					eaddr -= offset.un;
-				regs->uregs[rn] = eaddr;
-			} else if (LDST_W_BIT(instr))
-				regs->uregs[rn] = eaddr;
-			break;
+	if (!LDST_U_BIT(instr))
+		eaddr -= nr_regs;
+
+	/*
+	 * This is a "hint" - we already have eaddr worked out by the
+	 * processor for us.
+	 */
+	if (addr != eaddr)
+		printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, "
+			"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)) {
+				get32_unaligned_check(regs->uregs[rd], eaddr);
+				if (rd == 15)
+					correction = 0;
+			} else
+				put32_unaligned_check(regs->uregs[rd], eaddr);
+			eaddr += 4;
 		}
 
-	default:
-		ai_skipped += 1;
-		panic("Alignment trap: not handling instruction %08X at %08lX",
-				instr, regs->ARM_pc - correction - 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;
+	return TYPE_DONE;
+
+fault:
+	return TYPE_FAULT;
+
+bad:
+	printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n");
+	return TYPE_ERROR;
+}
+
+static int
+do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
+{
+	union offset_union offset;
+	unsigned long instr, instrptr;
+	int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
+	unsigned int type;
+
+	if (user_mode(regs))
+		goto user;
+
+	ai_sys += 1;
+
+	instrptr = instruction_pointer(regs);
+	instr = *(unsigned long *)instrptr;
+
+	regs->ARM_pc += 4;
+
+	switch (CODING_BITS(instr)) {
+	case 0x00000000:	/* ldrh or strh */
+		if (LDSTH_I_BIT(instr))
+			offset.un = (instr & 0xf00) >> 4 | (instr & 15);
+		else
+			offset.un = regs->uregs[RM_BITS(instr)];
+		handler = do_alignment_ldrhstrh;
 		break;
 
-	case 0x04000000:
+	case 0x04000000:	/* ldr or str immediate */
 		offset.un = OFFSET_BITS(instr);
-		goto ldr_str;
+		handler = do_alignment_ldrstr;
+		break;
 
-	case 0x06000000:
+	case 0x06000000:	/* ldr or str register */
 		offset.un = regs->uregs[RM_BITS(instr)];
 
 		if (IS_SHIFT(instr)) {
@@ -229,97 +466,49 @@
 				break;
 			}
 		}
-
-	ldr_str:
-		ai_word += 1;
-		if (LDST_P_BIT(instr)) {
-			if (LDST_U_BIT(instr))
-				eaddr += offset.un;
-			else
-				eaddr -= offset.un;
-		} else {
-			if (LDST_W_BIT(instr)) {
-				printk(KERN_ERR "Not handling ldrt/strt correctly\n");
-				return 1;
-			}
-		}
-
-		/*
-		 * This is a "hint" - we already have eaddr worked out by the
-		 * processor for us.
-		 */
-		if (addr != eaddr)
-			printk(KERN_ERR "LDRSTR: PC = %08lx, instr = %08x, "
-				"addr = %08lx, eaddr = %08lx\n",
-				 instruction_pointer(regs), instr, addr, eaddr);
-
-		if (LDST_L_BIT(instr)) {
-			regs->uregs[rd] = get_unaligned((unsigned long *)eaddr);
-			if (rd == 15)
-				correction = 0;
-		} else
-			put_unaligned(regs->uregs[rd], (unsigned long *)eaddr);
-
-		if (!LDST_P_BIT(instr)) {
-			if (LDST_U_BIT(instr))
-				eaddr += offset.un;
-			else
-				eaddr -= offset.un;
-
-			regs->uregs[rn] = eaddr;
-		} else if (LDST_W_BIT(instr))
-			regs->uregs[rn] = eaddr;
+		handler = do_alignment_ldrstr;
 		break;
 
-	case 0x08000000:
-		if (LDM_S_BIT(instr))
-			panic("Alignment trap: not handling LDM with s-bit\n");
-		ai_multi += 1;
-
-		for (regbits = REGMASK_BITS(instr), nr_regs = 0; regbits; regbits >>= 1)
-			nr_regs += 4;
+	case 0x08000000:	/* ldm or stm */
+		handler = do_alignment_ldmstm;
+		break;
 
-		if  (!LDST_U_BIT(instr))
-			eaddr -= nr_regs;
+	default:
+		goto bad;
+	}
 
-		/*
-		 * This is a "hint" - we already have eaddr worked out by the
-		 * processor for us.
-		 */
-		if (addr != eaddr)
-			printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08x, "
-				"addr = %08lx, eaddr = %08lx\n",
-				 instruction_pointer(regs), instr, addr, eaddr);
+	type = handler(addr, instr, regs);
 
-		if ((LDST_U_BIT(instr) == 0 && LDST_P_BIT(instr) == 0) ||
-		    (LDST_U_BIT(instr)      && LDST_P_BIT(instr)))
-			eaddr += 4;
+	if (type == TYPE_ERROR || type == TYPE_FAULT)
+		goto bad_or_fault;
 
-		for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1)
-			if (regbits & 1) {
-				if (LDST_L_BIT(instr)) {
-					regs->uregs[rd] = get_unaligned((unsigned long *)eaddr);
-					if (rd == 15)
-						correction = 0;
-				} else
-					put_unaligned(regs->uregs[rd], (unsigned long *)eaddr);
-				eaddr += 4;
-			}
+	if (type == TYPE_LDST)
+		do_alignment_finish_ldst(addr, instr, regs, offset);
 
-		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;
-		}
-		break;
-	}
+	return 0;
 
-	regs->ARM_pc -= correction;
+bad_or_fault:
+	if (type == TYPE_ERROR)
+		goto bad;
+	regs->ARM_pc -= 4;
+	/*
+	 * We got a fault - fix it up, or die.
+	 */
+	do_bad_area(current, current->mm, addr, error_code, regs);
+	return 0;
 
+bad:
+	/*
+	 * Oops, we didn't handle the instruction.
+	 */
+	printk(KERN_ERR "Alignment trap: not handling instruction "
+		"%08lx at [<%08lx>]", instr, instrptr);
+	ai_skipped += 1;
+	return 1;
+
+user:
+	set_cr(cr_no_alignment);
+	ai_user += 1;
 	return 0;
 }
 
@@ -332,35 +521,13 @@
 /*
  * Some section permission faults need to be handled gracefully, for
  * instance, when they happen due to a __{get,put}_user during an oops).
- * In this case, we should return an error to the __{get,put}_user caller
- * instead of causing another oops.  We should also fixup this fault as
- * the user could pass a pointer to a section to the kernel.
  */
 static int
 do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
 {
-	unsigned long fixup;
-
-	if (user_mode(regs)) {
-#ifdef CONFIG_DEBUG_USER
-		printk("%s: permission fault on section, "
-		       "address=0x%08lx, code %d\n",
-		       current->comm, addr, error_code);
-#endif
-		goto fail;
-	}
-
-	fixup = search_exception_table(instruction_pointer(regs));
-	if (fixup != 0) {
-#ifdef DEBUG
-		printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
-			tsk->comm, regs->ARM_pc, addr, fixup);
-#endif
-		regs->ARM_pc = fixup;
-		return 0;
-	}
-fail:
-	return 1;	/* not fixed up */
+	struct task_struct *tsk = current;
+	do_bad_area(tsk, tsk->active_mm, addr, error_code, regs);
+	return 0;
 }
 
 static const struct fsr_info {
@@ -369,17 +536,17 @@
 	char	*name;
 } fsr_info[] = {
 	{ NULL,			SIGSEGV, "vector exception"		   },
-	{ do_alignment,		SIGBUS,	 "alignment exception"		   },
+	{ do_alignment,		SIGILL,	 "alignment exception"		   },
 	{ NULL,			SIGKILL, "terminal exception"		   },
-	{ do_alignment,		SIGBUS,	 "alignment exception"		   },
+	{ do_alignment,		SIGILL,	 "alignment exception"		   },
 	{ NULL,			SIGBUS,	 "external abort on linefetch"	   },
-	{ do_page_fault,	SIGSEGV, "page fault"			   },
+	{ do_translation_fault,	SIGSEGV, "section translation fault"	   },
 	{ NULL,			SIGBUS,	 "external abort on linefetch"	   },
-	{ do_page_fault,	SIGSEGV, "page fault"			   },
+	{ do_page_fault,	SIGSEGV, "page translation fault"	   },
 	{ NULL,			SIGBUS,	 "external abort on non-linefetch" },
-	{ NULL,			SIGSEGV, "domain fault"			   },
+	{ NULL,			SIGSEGV, "section domain fault"		   },
 	{ NULL,			SIGBUS,	 "external abort on non-linefetch" },
-	{ NULL,			SIGSEGV, "domain fault"			   },
+	{ NULL,			SIGSEGV, "page domain fault"		   },
 	{ NULL,			SIGBUS,	 "external abort on translation"   },
 	{ do_sect_fault,	SIGSEGV, "section permission fault"	   },
 	{ NULL,			SIGBUS,	 "external abort on translation"   },
@@ -398,7 +565,7 @@
 	if (addr == regs->ARM_pc)
 		goto sa1_weirdness;
 #endif
-#if defined(CONFIG_CPU_ARM720T) && defined(CONFIG_ALIGNMENT_TRAP)
+#if defined(CONFIG_CPU_ARM720) && defined(CONFIG_ALIGNMENT_TRAP)
 	if (addr & 3 && (fsr & 13) != 1)
 		goto arm720_weirdness;
 #endif
@@ -410,7 +577,6 @@
 		return;
 bad:
 	force_sig(inf->sig, current);
-
 	printk(KERN_ALERT "Unhandled fault: %s (%X) at 0x%08lx\n",
 		inf->name, fsr, addr);
 	show_pte(current->mm, addr);
@@ -431,7 +597,7 @@
 		goto bad;
 	return;
 #endif
-#if defined(CONFIG_CPU_ARM720T) && defined(CONFIG_ALIGNMENT_TRAP)
+#if defined(CONFIG_CPU_ARM720) && defined(CONFIG_ALIGNMENT_TRAP)
 arm720_weirdness:
 	if (!user_mode(regs)) {
 		unsigned long instr;
@@ -462,6 +628,6 @@
 asmlinkage int
 do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
 {
-	do_page_fault(addr, 0, regs);
+	do_translation_fault(addr, 0, regs);
 	return 1;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/fault-common.c linux/arch/arm/mm/fault-common.c
--- v2.4.3/linux/arch/arm/mm/fault-common.c	Mon Mar 19 12:35:10 2001
+++ linux/arch/arm/mm/fault-common.c	Thu Apr 12 12:20:31 2001
@@ -2,7 +2,7 @@
  *  linux/arch/arm/mm/fault-common.c
  *
  *  Copyright (C) 1995  Linus Torvalds
- *  Modifications for ARM processor (c) 1995-1999 Russell King
+ *  Modifications for ARM processor (c) 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
@@ -93,8 +93,82 @@
 	printk("\n");
 }
 
+/*
+ * Oops.  The kernel tried to access some page that wasn't present.
+ */
+static void
+__do_kernel_fault(struct mm_struct *mm, unsigned long addr, int error_code,
+		  struct pt_regs *regs)
+{
+	unsigned long fixup;
+
+	/*
+	 * Are we prepared to handle this kernel fault?
+	 */
+	if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
+			tsk->comm, regs->ARM_pc, addr, fixup);
+#endif
+		regs->ARM_pc = fixup;
+		return;
+	}
+
+	/*
+	 * No handler, we'll have to terminate things with extreme prejudice.
+	 */
+	printk(KERN_ALERT
+		"Unable to handle kernel %s at virtual address %08lx\n",
+		(addr < PAGE_SIZE) ? "NULL pointer dereference" :
+		"paging request", addr);
+
+	show_pte(mm, addr);
+	die("Oops", regs, error_code);
+	do_exit(SIGKILL);
+}
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * User mode accesses just cause a SIGSEGV
+ */
+static void
+__do_user_fault(struct task_struct *tsk, unsigned long addr, int error_code,
+		int code, struct pt_regs *regs)
+{
+	struct siginfo si;
+
+#ifdef CONFIG_DEBUG_USER
+	printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, "
+	       "lr=0x%08lx (bad address=0x%08lx, code %d)\n",
+	       tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, error_code);
+#endif
+
+	tsk->thread.address = addr;
+	tsk->thread.error_code = error_code;
+	tsk->thread.trap_no = 14;
+	si.si_signo = SIGSEGV;
+	si.si_errno = 0;
+	si.si_code = code;
+	si.si_addr = (void *)addr;
+	force_sig_info(SIGSEGV, &si, tsk);
+}
+
+void
+do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
+	    int error_code, struct pt_regs *regs)
+{
+	/*
+	 * If we are in kernel mode at this point, we
+	 * have no context to handle this fault with.
+	 */
+	if (user_mode(regs))
+		__do_user_fault(tsk, addr, error_code, SEGV_MAPERR, regs);
+	else
+		__do_kernel_fault(mm, addr, error_code, regs);
+}
+
 static int
-__do_page_fault(struct mm_struct *mm, unsigned long addr, int mode,
+__do_page_fault(struct mm_struct *mm, unsigned long addr, int error_code,
 		struct task_struct *tsk)
 {
 	struct vm_area_struct *vma;
@@ -112,7 +186,7 @@
 	 * memory access, so we can handle it.
 	 */
 good_area:
-	if (READ_FAULT(mode)) /* read? */
+	if (READ_FAULT(error_code)) /* read? */
 		mask = VM_READ|VM_EXEC;
 	else
 		mask = VM_WRITE;
@@ -127,7 +201,7 @@
 	 * than endlessly redo the fault.
 	 */
 survive:
-	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(mode));
+	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(error_code));
 
 	/*
 	 * Handle the "normal" cases first - successful and sigbus
@@ -161,62 +235,16 @@
 	return fault;
 }
 
-static int __do_vmalloc_fault(unsigned long addr, struct mm_struct *mm)
-{
-	/* Synchronise this task's top level page-table
-	 * with the 'reference' page table.
-	 */
-	int offset = __pgd_offset(addr);
-	pgd_t *pgd, *pgd_k;
-	pmd_t *pmd, *pmd_k;
-
-	pgd_k = init_mm.pgd + offset;
-	if (!pgd_present(*pgd_k))
-		goto bad_area;
-
-	pgd = mm->pgd + offset;
-#if 0	/* note that we are two-level */
-	if (!pgd_present(*pgd))
-		set_pgd(pgd, *pgd_k);
-#endif
-
-	pmd_k = pmd_offset(pgd_k, addr);
-	if (pmd_none(*pmd_k))
-		goto bad_area;
-
-	pmd = pmd_offset(pgd, addr);
-	if (!pmd_none(*pmd))
-		goto bad_area;
-	set_pmd(pmd, *pmd_k);
-	return 1;
-
-bad_area:
-	return -2;
-}
-
-int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
+int do_page_fault(unsigned long addr, int error_code, struct pt_regs *regs)
 {
 	struct task_struct *tsk;
 	struct mm_struct *mm;
-	unsigned long fixup;
 	int fault;
 
 	tsk = current;
 	mm  = tsk->mm;
 
 	/*
-	 * We fault-in kernel-space virtual memory on-demand. The
-	 * 'reference' page table is init_mm.pgd.
-	 *
-	 * NOTE! We MUST NOT take any locks for this case. We may
-	 * be in an interrupt or a critical region, and should
-	 * only copy the information from the master page table,
-	 * nothing more.
-	 */
-	if (addr >= TASK_SIZE)
-		goto vmalloc_fault;
-
-	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
 	 */
@@ -224,10 +252,9 @@
 		goto no_context;
 
 	down_read(&mm->mmap_sem);
-	fault = __do_page_fault(mm, addr, mode, tsk);
+	fault = __do_page_fault(mm, addr, error_code, tsk);
 	up_read(&mm->mmap_sem);
 
-ret:
 	/*
 	 * Handle the "normal" case first
 	 */
@@ -255,28 +282,9 @@
 		 */
 		printk("VM: killing process %s\n", tsk->comm);
 		do_exit(SIGKILL);
-	} else {
-		/*
-		 * Something tried to access memory that isn't in our memory map..
-		 * User mode accesses just cause a SIGSEGV
-		 */
-		struct siginfo si;
-
-#ifdef CONFIG_DEBUG_USER
-		printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, "
-		       "lr=0x%08lx (bad address=0x%08lx, code %d)\n",
-		       tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
-#endif
-
-		tsk->thread.address = addr;
-		tsk->thread.error_code = mode;
-		tsk->thread.trap_no = 14;
-		si.si_signo = SIGSEGV;
-		si.si_errno = 0;
-		si.si_code = fault == -1 ? SEGV_ACCERR : SEGV_MAPERR;
-		si.si_addr = (void *)addr;
-		force_sig_info(SIGSEGV, &si, tsk);
-	}
+	} else
+		__do_user_fault(tsk, addr, error_code, fault == -1 ?
+				SEGV_ACCERR : SEGV_MAPERR, regs);
 	return 0;
 
 
@@ -290,7 +298,7 @@
 	 * or user mode.
 	 */
 	tsk->thread.address = addr;
-	tsk->thread.error_code = mode;
+	tsk->thread.error_code = error_code;
 	tsk->thread.trap_no = 14;
 	force_sig(SIGBUS, tsk);
 
@@ -299,32 +307,64 @@
 		return 0;
 
 no_context:
-	/* Are we prepared to handle this kernel fault?  */
-	if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
-#ifdef DEBUG
-		printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
-			tsk->comm, regs->ARM_pc, addr, fixup);
+	__do_kernel_fault(mm, addr, error_code, regs);
+	return 0;
+}
+
+/*
+ * First Level Translation Fault Handler
+ *
+ * We enter here because the first level page table doesn't contain
+ * a valid entry for the address.
+ *
+ * If the address is in kernel space (>= TASK_SIZE), then we are
+ * probably faulting in the vmalloc() area.
+ *
+ * If the init_task's first level page tables contains the relevant
+ * entry, we copy the it to this task.  If not, we send the process
+ * a signal, fixup the exception, or oops the kernel.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may be in an
+ * interrupt or a critical region, and should only copy the information
+ * from the master page table, nothing more.
+ */
+int do_translation_fault(unsigned long addr, int error_code, struct pt_regs *regs)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	int offset;
+	pgd_t *pgd, *pgd_k;
+	pmd_t *pmd, *pmd_k;
+
+	if (addr < TASK_SIZE)
+		return do_page_fault(addr, error_code, regs);
+
+	tsk = current;
+	mm  = tsk->active_mm;
+
+	offset = __pgd_offset(addr);
+
+	pgd_k = init_mm.pgd + offset;
+	pgd   = mm->pgd + offset;
+
+	if (pgd_none(*pgd_k))
+		goto bad_area;
+
+#if 0	/* note that we are two-level */
+	if (!pgd_present(*pgd))
+		set_pgd(pgd, *pgd_k);
 #endif
-		regs->ARM_pc = fixup;
-		return 0;
-	}
 
-	/*
-	 * Oops. The kernel tried to access some bad page. We'll have to
-	 * terminate things with extreme prejudice.
-	 */
-	printk(KERN_ALERT
-		"Unable to handle kernel %s at virtual address %08lx\n",
-		(addr < PAGE_SIZE) ? "NULL pointer dereference" :
-		"paging request", addr);
+	pmd_k = pmd_offset(pgd_k, addr);
+	pmd   = pmd_offset(pgd, addr);
 
-	show_pte(mm, addr);
-	die("Oops", regs, mode);
-	do_exit(SIGKILL);
+	if (pmd_none(*pmd_k))
+		goto bad_area;
 
+	set_pmd(pmd, *pmd_k);
 	return 0;
 
-vmalloc_fault:
-	fault = __do_vmalloc_fault(addr, mm);
-	goto ret;
+bad_area:
+	do_bad_area(tsk, mm, addr, error_code, regs);
+	return 0;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c
--- v2.4.3/linux/arch/arm/mm/init.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/mm/init.c	Thu Apr 12 12:20:31 2001
@@ -59,52 +59,10 @@
 static struct meminfo meminfo __initdata = { 0, };
 
 /*
- * empty_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..
- *
- * empty_bad_pte_table is the accompanying page-table: it is
- * initialized to point to BAD_PAGE entries.
- *
  * empty_zero_page is a special page that is used for
  * zero-initialized data and COW.
  */
 struct page *empty_zero_page;
-struct page *empty_bad_page;
-pte_t *empty_bad_pte_table;
-
-pte_t *get_bad_pte_table(void)
-{
-	pte_t v;
-	int i;
-
-	v = pte_mkdirty(mk_pte(empty_bad_page, PAGE_SHARED));
-
-	for (i = 0; i < PTRS_PER_PTE; i++)
-		set_pte(empty_bad_pte_table + i, v);
-
-	return empty_bad_pte_table;
-}
-
-void __handle_bad_pmd(pmd_t *pmd)
-{
-	pmd_ERROR(*pmd);
-#ifdef CONFIG_DEBUG_ERRORS
-	__backtrace();
-#endif
-	set_pmd(pmd, mk_user_pmd(get_bad_pte_table()));
-}
-
-void __handle_bad_pmd_kernel(pmd_t *pmd)
-{
-	pmd_ERROR(*pmd);
-#ifdef CONFIG_DEBUG_ERRORS
-	__backtrace();
-#endif
-	set_pmd(pmd, mk_kernel_pmd(get_bad_pte_table()));
-}
 
 #ifndef CONFIG_NO_PGT_CACHE
 struct pgtable_cache_struct quicklists;
@@ -120,12 +78,12 @@
 				freed++;
 			}
 			if(pmd_quicklist) {
-				free_pmd_slow(get_pmd_fast());
+				pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
 				freed++;
 			}
 			if(pte_quicklist) {
-				free_pte_slow(get_pte_fast());
-				 freed++;
+				pte_free_slow(pte_alloc_one_fast(NULL, 0));
+				freed++;
 			}
 		} while(pgtable_cache_size > low);
 	}
@@ -514,18 +472,15 @@
  */
 void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
 {
-	void *zero_page, *bad_page, *bad_table;
+	void *zero_page;
 	int node;
 
 	memcpy(&meminfo, mi, sizeof(meminfo));
 
 	/*
-	 * allocate what we need for the bad pages.
-	 * note that we count on this going ok.
+	 * allocate the zero page.  Note that we count on this going ok.
 	 */
 	zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
-	bad_page  = alloc_bootmem_low_pages(PAGE_SIZE);
-	bad_table = alloc_bootmem_low_pages(TABLE_SIZE);
 
 	/*
 	 * initialise the page tables.
@@ -586,11 +541,7 @@
 	 * the mem_map is initialised
 	 */
 	memzero(zero_page, PAGE_SIZE);
-	memzero(bad_page, PAGE_SIZE);
-
 	empty_zero_page = virt_to_page(zero_page);
-	empty_bad_page  = virt_to_page(bad_page);
-	empty_bad_pte_table = ((pte_t *)bad_table) + TABLE_OFFSET;
 }
 
 /*
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/ioremap.c linux/arch/arm/mm/ioremap.c
--- v2.4.3/linux/arch/arm/mm/ioremap.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/ioremap.c	Thu Apr 12 12:20:31 2001
@@ -44,14 +44,18 @@
 	end = address + size;
 	if (end > PMD_SIZE)
 		end = PMD_SIZE;
+	if (address >= end)
+		BUG();
 	do {
-		if (!pte_none(*pte))
+		if (!pte_none(*pte)) {
 			printk("remap_area_pte: page already exists\n");
+			BUG();
+		}
 		set_pte(pte, mk_pte_phys(phys_addr, pgprot));
 		address += PAGE_SIZE;
 		phys_addr += PAGE_SIZE;
 		pte++;
-	} while (address < end);
+	} while (address && (address < end));
 }
 
 static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
@@ -67,40 +71,50 @@
 		end = PGDIR_SIZE;
 
 	phys_addr -= address;
+	if (address >= end)
+		BUG();
+
 	pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags);
 	do {
-		pte_t * pte = pte_alloc_kernel(pmd, address);
+		pte_t * pte = pte_alloc(&init_mm, pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, pgprot);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
-	} while (address < end);
+	} while (address && (address < end));
 	return 0;
 }
 
 static int remap_area_pages(unsigned long address, unsigned long phys_addr,
 				 unsigned long size, unsigned long flags)
 {
+	int error;
 	pgd_t * dir;
 	unsigned long end = address + size;
 
 	phys_addr -= address;
 	dir = pgd_offset(&init_mm, address);
 	flush_cache_all();
-	while (address < end) {
-		pmd_t *pmd = pmd_alloc_kernel(dir, address);
+	if (address >= end)
+		BUG();
+	spin_lock(&init_mm.page_table_lock);
+	do {
+		pmd_t *pmd;
+		pmd = pmd_alloc(&init_mm, dir, address);
+		error = -ENOMEM;
 		if (!pmd)
-			return -ENOMEM;
+			break;
 		if (remap_area_pmd(pmd, address, end - address,
 					 phys_addr + address, flags))
-			return -ENOMEM;
-		set_pgdir(address, *dir);
+			break;
+		error = 0;
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
-	}
+	} while (address && (address < end));
+	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
-	return 0;
+	return error;
 }
 
 /*
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/mm-armo.c linux/arch/arm/mm/mm-armo.c
--- v2.4.3/linux/arch/arm/mm/mm-armo.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/mm-armo.c	Thu Apr 12 12:20:31 2001
@@ -22,120 +22,98 @@
 #include <asm/mach/map.h>
 
 #define MEMC_TABLE_SIZE (256*sizeof(unsigned long))
-#define PGD_TABLE_SIZE	(PTRS_PER_PGD * BYTES_PER_PTR)
 
+kmem_cache_t *pte_cache, *pgd_cache;
 int page_nr;
 
-extern unsigned long get_page_2k(int prio);
-extern void free_page_2k(unsigned long);
-extern pte_t *get_bad_pte_table(void);
-
 /*
  * Allocate a page table.  Note that we place the MEMC
  * table before the page directory.  This means we can
  * easily get to both tightly-associated data structures
  * with a single pointer.
- *
- * We actually only need 1152 bytes, 896 bytes is wasted.
- * We could try to fit 7 PTEs into that slot somehow.
  */
-static inline void *alloc_pgd_table(int priority)
+static inline pgd_t *alloc_pgd_table(int priority)
 {
-	unsigned long pg2k;
+	void *pg2k = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
 
-	pg2k = get_page_2k(priority);
 	if (pg2k)
 		pg2k += MEMC_TABLE_SIZE;
 
-	return (void *)pg2k;
+	return (pgd_t *)pg2k;
 }
 
 void free_pgd_slow(pgd_t *pgd)
 {
 	unsigned long tbl = (unsigned long)pgd;
 
+	/*
+	 * CHECKME: are we leaking pte tables here???
+	 */
+
 	tbl -= MEMC_TABLE_SIZE;
-	free_page_2k(tbl);
+
+	kmem_cache_free(pgd_cache, (void *)tbl);
 }
 
-/*
- * FIXME: the following over-allocates by 1600%
- */
-static inline void *alloc_pte_table(int size, int prio)
+pgd_t *get_pgd_slow(struct mm_struct *mm)
 {
-	if (size != 128)
-		printk("invalid table size\n");
-	return (void *)get_page_2k(prio);
-}
-
-void free_pte_slow(pte_t *pte)
-{
-	unsigned long tbl = (unsigned long)pte;
-	free_page_2k(tbl);
-}
-
-pgd_t *get_pgd_slow(void)
-{
-	pgd_t *pgd = (pgd_t *)alloc_pgd_table(GFP_KERNEL);
-	pmd_t *new_pmd;
-
-	if (pgd) {
-		pgd_t *init = pgd_offset(&init_mm, 0);
-		
-		memzero(pgd, USER_PTRS_PER_PGD * sizeof(pgd_t));
-		memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
-			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-
-		/*
-		 * On ARM, first page must always be allocated
-		 */
-		if (!pmd_alloc(pgd, 0))
-			goto nomem;
-		else {
-			pmd_t *old_pmd = pmd_offset(init, 0);
-			new_pmd = pmd_offset(pgd, 0);
-
-			if (!pte_alloc(new_pmd, 0))
-				goto nomem_pmd;
-			else {
-				pte_t *new_pte = pte_offset(new_pmd, 0);
-				pte_t *old_pte = pte_offset(old_pmd, 0);
-
-				set_pte (new_pte, *old_pte);
-			}
-		}
-		/* update MEMC tables */
-		cpu_memc_update_all(pgd);
-	}
-	return pgd;
+	pgd_t *new_pgd, *init_pgd;
+	pmd_t *new_pmd, *init_pmd;
+	pte_t *new_pte, *init_pte;
+
+	new_pgd = alloc_pgd_table(GFP_KERNEL);
+	if (!new_pgd)
+		goto no_pgd;
+
+	/*
+	 * 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;
 
-nomem_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);
+
+	/*
+	 * most of the page table entries are zeroed
+	 * wne the table is created.
+	 */
+	memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD,
+		(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+
+	spin_unlock(&mm->page_table_lock);
+
+	/* update MEMC tables */
+	cpu_memc_update_all(new_pgd);
+	return new_pgd;
+
+no_pte:
+	spin_unlock(&mm->page_table_lock);
 	pmd_free(new_pmd);
-nomem:
-	free_pgd_slow(pgd);
+	free_pgd_slow(new_pgd);
 	return NULL;
-}
 
-pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
-{
-	pte_t *pte;
+no_pmd:
+	spin_unlock(&mm->page_table_lock);
+	free_pgd_slow(new_pgd);
+	return NULL;
 
-	pte = (pte_t *)alloc_pte_table(PTRS_PER_PTE * sizeof(pte_t), GFP_KERNEL);
-	if (pmd_none(*pmd)) {
-		if (pte) {
-			memzero(pte, PTRS_PER_PTE * sizeof(pte_t));
-			set_pmd(pmd, mk_user_pmd(pte));
-			return pte + offset;
-		}
-		set_pmd(pmd, mk_user_pmd(get_bad_pte_table()));
-		return NULL;
-	}
-	free_pte_slow(pte);
-	if (pmd_bad(*pmd)) {
-		__handle_bad_pmd(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + offset;
+no_pgd:
+	return NULL;
 }
 
 /*
@@ -160,7 +138,7 @@
 
 	pte = alloc_bootmem_low_pages(PTRS_PER_PTE * sizeof(pte_t));
 	pte[0] = mk_pte_phys(PAGE_OFFSET + 491520, PAGE_READONLY);
-	set_pmd(pmd_offset(swapper_pg_dir, 0), mk_kernel_pmd(pte));
+	pmd_populate(&init_mm, pmd_offset(swapper_pg_dir, 0), pte);
 
 	for (i = 1; i < PTRS_PER_PGD; i++)
 		pgd_val(swapper_pg_dir[i]) = 0;
@@ -176,4 +154,31 @@
  */
 void __init create_memmap_holes(struct meminfo *mi)
 {
+}
+
+static void pte_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
+{
+	memzero(pte, sizeof(pte_t) * PTRS_PER_PTE);
+}
+
+static void pgd_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
+{
+	pgd_t *pgd = (pte + MEMC_TABLE_SIZE);
+
+	memzero(pgd, USER_PTRS_PER_PGD * sizeof(pgd_t));
+}
+
+void __init pgtable_cache_init(void)
+{
+	pte_cache = kmem_cache_create("pte-cache",
+				sizeof(pte_t) * PTRS_PER_PTE,
+				0, 0, pte_cache_ctor, NULL);
+	if (!pte_cache)
+		BUG();
+
+	pgd_cache = kmem_cache_create("pgd-cache", MEMC_TABLE_SIZE +
+				sizeof(pgd_t) * PTRS_PER_PGD,
+				0, 0, pgd_cache_ctor, NULL);
+	if (!pgd_cache)
+		BUG();
 }
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- v2.4.3/linux/arch/arm/mm/mm-armv.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/mm/mm-armv.c	Thu Apr 12 12:20:31 2001
@@ -22,12 +22,6 @@
 
 #include <asm/mach/map.h>
 
-unsigned long *valid_addr_bitmap;
-
-extern unsigned long get_page_2k(int priority);
-extern void free_page_2k(unsigned long page);
-extern pte_t *get_bad_pte_table(void);
-
 /*
  * These are useful for identifing cache coherency
  * problems by allowing the cache or the cache and
@@ -73,47 +67,68 @@
 /*
  * need to get a 16k page for level 1
  */
-pgd_t *get_pgd_slow(void)
+pgd_t *get_pgd_slow(struct mm_struct *mm)
 {
-	pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL,2);
-	pmd_t *new_pmd;
+	pgd_t *new_pgd, *init_pgd;
+	pmd_t *new_pmd, *init_pmd;
+	pte_t *new_pte, *init_pte;
+
+	new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2);
+	if (!new_pgd)
+		goto no_pgd;
+
+	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);
 
-	if (pgd) {
-		pgd_t *init = 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;
+
+	init_pgd = pgd_offset_k(0);
+	init_pmd = pmd_offset(init_pgd, 0);
+	init_pte = pte_offset(init_pmd, 0);
 
-		memzero(pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
-		memcpy(pgd  + FIRST_KERNEL_PGD_NR, init + FIRST_KERNEL_PGD_NR,
+	set_pte(new_pte, *init_pte);
+
+	/*
+	 * Copy over the kernel and IO PGD entries
+	 */
+	memcpy(new_pgd  + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
 		       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
-		/*
-		 * FIXME: this should not be necessary
-		 */
-		clean_cache_area(pgd, PTRS_PER_PGD * sizeof(pgd_t));
 
-		/*
-		 * On ARM, first page must always be allocated
-		 */
-		if (!pmd_alloc(pgd, 0))
-			goto nomem;
-		else {
-			pmd_t *old_pmd = pmd_offset(init, 0);
-			new_pmd = pmd_offset(pgd, 0);
-
-			if (!pte_alloc(new_pmd, 0))
-				goto nomem_pmd;
-			else {
-				pte_t *new_pte = pte_offset(new_pmd, 0);
-				pte_t *old_pte = pte_offset(old_pmd, 0);
+	spin_unlock(&mm->page_table_lock);
 
-				set_pte(new_pte, *old_pte);
-			}
-		}
-	}
-	return pgd;
+	/*
+	 * FIXME: this should not be necessary
+	 */
+	clean_cache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
+
+	return new_pgd;
 
-nomem_pmd:
+no_pte:
+	spin_unlock(&mm->page_table_lock);
 	pmd_free(new_pmd);
-nomem:
-	free_pages((unsigned long)pgd, 2);
+	free_pages((unsigned long)new_pgd, 2);
+	return NULL;
+
+no_pmd:
+	spin_unlock(&mm->page_table_lock);
+	free_pages((unsigned long)new_pgd, 2);
+	return NULL;
+
+no_pgd:
 	return NULL;
 }
 
@@ -142,59 +157,6 @@
 	free_pages((unsigned long) pgd, 2);
 }
 
-pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
-{
-	pte_t *pte;
-
-	pte = (pte_t *)get_page_2k(GFP_KERNEL);
-	if (pmd_none(*pmd)) {
-		if (pte) {
-			memzero(pte, 2 * PTRS_PER_PTE * sizeof(pte_t));
-			clean_cache_area(pte, PTRS_PER_PTE * sizeof(pte_t));
-			pte += PTRS_PER_PTE;
-			set_pmd(pmd, mk_user_pmd(pte));
-			return pte + offset;
-		}
-		set_pmd(pmd, mk_user_pmd(get_bad_pte_table()));
-		return NULL;
-	}
-	free_page_2k((unsigned long)pte);
-	if (pmd_bad(*pmd)) {
-		__handle_bad_pmd(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + offset;
-}
-
-pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
-{
-	pte_t *pte;
-
-	pte = (pte_t *)get_page_2k(GFP_KERNEL);
-	if (pmd_none(*pmd)) {
-		if (pte) {
-			memzero(pte, 2 * PTRS_PER_PTE * sizeof(pte_t));
-			clean_cache_area(pte, PTRS_PER_PTE * sizeof(pte_t));
-			pte += PTRS_PER_PTE;
-			set_pmd(pmd, mk_kernel_pmd(pte));
-			return pte + offset;
-		}
-		set_pmd(pmd, mk_kernel_pmd(get_bad_pte_table()));
-		return NULL;
-	}
-	free_page_2k((unsigned long)pte);
-	if (pmd_bad(*pmd)) {
-		__handle_bad_pmd_kernel(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + offset;
-}
-
-void free_pte_slow(pte_t *pte)
-{
-	free_page_2k((unsigned long)(pte - PTRS_PER_PTE));
-}
-
 /*
  * Create a SECTION PGD between VIRT and PHYS in domain
  * DOMAIN with protection PROT
@@ -481,4 +443,42 @@
 
 	for (node = 0; node < numnodes; node++)
 		free_unused_memmap_node(node, mi);
+}
+
+/*
+ * PTE table allocation cache.
+ *
+ * This is a move away from our custom 2K page allocator.  We now use the
+ * slab cache to keep track of these objects.
+ *
+ * With this, it is questionable as to whether the PGT cache gains us
+ * anything.  We may be better off dropping the PTE stuff from our PGT
+ * cache implementation.
+ */
+kmem_cache_t *pte_cache;
+
+/*
+ * The constructor gets called for each object within the cache when the
+ * cache page is created.  Note that if slab tries to misalign the blocks,
+ * we BUG() loudly.
+ */
+static void pte_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
+{
+	unsigned long block = (unsigned long)pte;
+
+	if (block & 2047)
+		BUG();
+
+	memzero(pte, 2 * PTRS_PER_PTE * sizeof(pte_t));
+	cpu_cache_clean_invalidate_range(block, block +
+			PTRS_PER_PTE * sizeof(pte_t), 0);
+}
+
+void __init pgtable_cache_init(void)
+{
+	pte_cache = kmem_cache_create("pte-cache",
+				2 * PTRS_PER_PTE * sizeof(pte_t), 0, 0,
+				pte_cache_ctor, NULL);
+	if (!pte_cache)
+		BUG();
 }
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/mm-clps7500.c linux/arch/arm/mm/mm-clps7500.c
--- v2.4.3/linux/arch/arm/mm/mm-clps7500.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/mm-clps7500.c	Thu Apr 12 12:20:31 2001
@@ -6,6 +6,7 @@
  *
  * Extra MM routines for CL7500 architecture
  */
+#include <linux/types.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/mm-ebsa110.c linux/arch/arm/mm/mm-ebsa110.c
--- v2.4.3/linux/arch/arm/mm/mm-ebsa110.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/mm-ebsa110.c	Wed Dec 31 16:00:00 1969
@@ -1,30 +0,0 @@
-/*
- *  linux/arch/arm/mm/mm-ebsa110.c
- *
- *  Copyright (C) 1998-1999 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
- * published by the Free Software Foundation.
- *
- *  Extra MM routines for the EBSA-110 architecture
- */
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
- 
-static struct map_desc ebsa110_io_desc[] __initdata = {
-	{ IO_BASE - PGDIR_SIZE, 0xc0000000, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
-	{ IO_BASE             , IO_START  , IO_SIZE   , DOMAIN_IO, 0, 1, 0, 0 },
-	LAST_DESC
-};
-
-void __init ebsa110_map_io(void)
-{
-	iotable_init(ebsa110_io_desc);
-}
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/mm-footbridge.c linux/arch/arm/mm/mm-footbridge.c
--- v2.4.3/linux/arch/arm/mm/mm-footbridge.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/mm-footbridge.c	Wed Dec 31 16:00:00 1969
@@ -1,117 +0,0 @@
-/*
- *  linux/arch/arm/mm/mm-footbridge.c
- *
- *  Copyright (C) 1998-2000 Russell King, Dave Gilbert.
- *
- * 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
- * published by the Free Software Foundation.
- *
- *  Extra MM routines for the EBSA285 architecture
- */
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
- 
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/hardware/dec21285.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/map.h>
-
-/*
- * Common mapping for all systems.  Note that the outbound write flush is
- * commented out since there is a "No Fix" problem with it.  Not mapping
- * it means that we have extra bullet protection on our feet.
- */
-static struct map_desc fb_common_io_desc[] __initdata = {
- { ARMCSR_BASE,	 DC21285_ARMCSR_BASE,	    ARMCSR_SIZE,  DOMAIN_IO, 0, 1, 0, 0 },
- { XBUS_BASE,    0x40000000,		    XBUS_SIZE,    DOMAIN_IO, 0, 1, 0, 0 },
- LAST_DESC
-};
-
-/*
- * The mapping when the footbridge is in host mode.  We don't map any of
- * this when we are in add-in mode.
- */
-static struct map_desc ebsa285_host_io_desc[] __initdata = {
-#if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_FOOTBRIDGE_HOST)
- { PCIMEM_BASE,  DC21285_PCI_MEM,	    PCIMEM_SIZE,  DOMAIN_IO, 0, 1, 0, 0 },
- { PCICFG0_BASE, DC21285_PCI_TYPE_0_CONFIG, PCICFG0_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
- { PCICFG1_BASE, DC21285_PCI_TYPE_1_CONFIG, PCICFG1_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
- { PCIIACK_BASE, DC21285_PCI_IACK,	    PCIIACK_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
- { PCIO_BASE,    DC21285_PCI_IO,	    PCIO_SIZE,	  DOMAIN_IO, 0, 1, 0, 0 },
-#endif
- LAST_DESC
-};
-
-/*
- * The CO-ebsa285 mapping.
- */
-static struct map_desc co285_io_desc[] __initdata = {
-#ifdef CONFIG_ARCH_CO285
- { PCIO_BASE,	 DC21285_PCI_IO,	    PCIO_SIZE,    DOMAIN_IO, 0, 1, 0, 0 },
- { PCIMEM_BASE,	 DC21285_PCI_MEM,	    PCIMEM_SIZE,  DOMAIN_IO, 0, 1, 0, 0 },
-#endif
- LAST_DESC
-};
-
-void __init footbridge_map_io(void)
-{
-	struct map_desc *desc = NULL;
-
-	/*
-	 * Set up the common mapping first; we need this to
-	 * determine whether we're in host mode or not.
-	 */
-	iotable_init(fb_common_io_desc);
-
-	/*
-	 * Now, work out what we've got to map in addition on this
-	 * platform.
-	 */
-	if (machine_is_co285())
-		desc = co285_io_desc;
-	else if (footbridge_cfn_mode())
-		desc = ebsa285_host_io_desc;
-
-	if (desc)
-		iotable_init(desc);
-}
-
-#ifdef CONFIG_FOOTBRIDGE_ADDIN
-
-/*
- * These two functions convert virtual addresses to PCI addresses and PCI
- * addresses to virtual addresses.  Note that it is only legal to use these
- * on memory obtained via get_free_page or kmalloc.
- */
-unsigned long __virt_to_bus(unsigned long res)
-{
-#ifdef CONFIG_DEBUG_ERRORS
-	if (res < PAGE_OFFSET || res >= (unsigned long)high_memory) {
-		printk("__virt_to_bus: invalid virtual address 0x%08lx\n", res);
-		__backtrace();
-	}
-#endif
-	return (res - PAGE_OFFSET) + (*CSR_PCISDRAMBASE & 0xfffffff0);
-}
-
-unsigned long __bus_to_virt(unsigned long res)
-{
-	res -= (*CSR_PCISDRAMBASE & 0xfffffff0);
-	res += PAGE_OFFSET;
-
-#ifdef CONFIG_DEBUG_ERRORS
-	if (res < PAGE_OFFSET || res >= (unsigned long)high_memory) {
-		printk("__bus_to_virt: invalid virtual address 0x%08lx\n", res);
-		__backtrace();
-	}
-#endif
-	return res;
-}
-
-#endif
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/mm-l7200.c linux/arch/arm/mm/mm-l7200.c
--- v2.4.3/linux/arch/arm/mm/mm-l7200.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/mm-l7200.c	Thu Apr 12 12:20:31 2001
@@ -17,6 +17,9 @@
 static struct map_desc l7200_io_desc[] __initdata = {
 	{ IO_BASE,	IO_START,	IO_SIZE,	DOMAIN_IO, 0, 1 ,0 ,0},
 	{ IO_BASE_2,	IO_START_2,	IO_SIZE_2,	DOMAIN_IO, 0, 1 ,0 ,0},
+	{ AUX_BASE,     AUX_START,      AUX_SIZE,       DOMAIN_IO, 0, 1 ,0 ,0},
+	{ FLASH1_BASE,  FLASH1_START,   FLASH1_SIZE,    DOMAIN_IO, 0, 1 ,0 ,0},
+	{ FLASH2_BASE,  FLASH2_START,   FLASH2_SIZE,    DOMAIN_IO, 0, 1 ,0 ,0},
 	LAST_DESC
 };
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/mm-sa1100.c linux/arch/arm/mm/mm-sa1100.c
--- v2.4.3/linux/arch/arm/mm/mm-sa1100.c	Fri Mar  2 11:12:06 2001
+++ linux/arch/arm/mm/mm-sa1100.c	Thu Apr 12 12:20:31 2001
@@ -15,9 +15,8 @@
  *
  */
 #include <linux/config.h>
-#include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/bootmem.h>
 
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
@@ -109,22 +108,9 @@
   LAST_DESC
 };
 
-static struct map_desc thinclient_io_desc[] __initdata = {
-#ifdef CONFIG_SA1100_THINCLIENT
-#if 0
-  { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */
-#else
-  { 0xe8000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */
-#endif
-  { 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
-#endif
-  LAST_DESC
-};
-
-static struct map_desc tifon_io_desc[] __initdata = {
-#ifdef CONFIG_SA1100_TIFON
-  { 0xe8000000, 0x00000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
-  { 0xe8800000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 2 */
+static struct map_desc sherman_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_SHERMAN
+  { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash*/
 #endif
   LAST_DESC
 };
@@ -138,9 +124,16 @@
 
 static struct map_desc xp860_io_desc[] __initdata = {
 #ifdef CONFIG_SA1100_XP860
-  { 0xf4000000, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
   { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SCSI */
   { 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* LAN */
+  { 0xf4000000, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+#endif
+  LAST_DESC
+};
+
+static struct map_desc pangolin_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_PANGOLIN
+  { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
 #endif
   LAST_DESC
 };
@@ -153,8 +146,6 @@
 
 	if (machine_is_assabet())
 		desc = assabet_io_desc;
-	else if (machine_is_nanoengine())
-		desc = nanoengine_io_desc;
 	else if (machine_is_bitsy())
 		desc = bitsy_io_desc;
 	else if (machine_is_cerf())
@@ -165,38 +156,21 @@
 		desc = graphicsclient_io_desc;
 	else if (machine_is_lart())
 	        desc = lart_io_desc;
-	else if (machine_is_thinclient())
-		desc = thinclient_io_desc;
-	else if (machine_is_tifon())
-		desc = tifon_io_desc;
+	else if (machine_is_nanoengine())
+		desc = nanoengine_io_desc;
+	else if (machine_is_sherman())
+		desc = sherman_io_desc;
 	else if (machine_is_victor())
 		desc = victor_io_desc;
 	else if (machine_is_xp860())
 		desc = xp860_io_desc;
+	else if (machine_is_pangolin())
+		desc = pangolin_io_desc;
 
 	if (desc)
 		iotable_init(desc);
 }
 
-
-#ifdef CONFIG_DISCONTIGMEM
-
-/*
- * Our node_data structure for discontigous memory.
- * There is 4 possible nodes i.e. the 4 SA1100 RAM banks.
- */
-
-static bootmem_data_t node_bootmem_data[4];
-
-pg_data_t sa1100_node_data[4] =
-{ { bdata: &node_bootmem_data[0] },
-  { bdata: &node_bootmem_data[1] },
-  { bdata: &node_bootmem_data[2] },
-  { bdata: &node_bootmem_data[3] } };
-
-#endif
-
-  
 /*
  * On Assabet, we must probe for the Neponset board *before* paging_init() 
  * has occurred to actually determine the amount of RAM available.  To do so, 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S
--- v2.4.3/linux/arch/arm/mm/proc-sa110.S	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/mm/proc-sa110.S	Thu Apr 12 12:20:31 2001
@@ -556,7 +556,7 @@
 	mov	pc, lr
 
 /*
- * cpu_sa110_arm920_set_pte(ptep, pte)
+ * cpu_sa110_set_pte(ptep, pte)
  *
  * Set a PTE and flush it out
  */
@@ -737,7 +737,7 @@
 	b	__sa110_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
 	.long	cpu_sa110_info
 	.long	sa110_processor_functions
 	.size	__sa110_proc_info, . - __sa110_proc_info
@@ -750,7 +750,7 @@
 	b	__sa1100_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
 	.long	cpu_sa1100_info
 	.long	sa1100_processor_functions
 	.size	__sa1100_proc_info, . - __sa1100_proc_info
@@ -763,7 +763,7 @@
 	b	__sa1100_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT
 	.long	cpu_sa1110_info
 	.long	sa1100_processor_functions
 	.size	__sa1110_proc_info, . - __sa1110_proc_info
diff -u --recursive --new-file v2.4.3/linux/arch/arm/mm/small_page.c linux/arch/arm/mm/small_page.c
--- v2.4.3/linux/arch/arm/mm/small_page.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/small_page.c	Thu Apr 12 12:20:31 2001
@@ -202,17 +202,6 @@
 	printk("Trying to free free small page from %p\n", __builtin_return_address(0));
 }
 
-unsigned long get_page_2k(int priority)
-{
-	return __get_small_page(priority, orders+0);
-}
-
-void free_page_2k(unsigned long spage)
-{
-	__free_small_page(spage, orders+0);
-}
-
-#if PAGE_SIZE > 8192
 unsigned long get_page_8k(int priority)
 {
 	return __get_small_page(priority, orders+1);
@@ -222,4 +211,3 @@
 {
 	__free_small_page(spage, orders+1);
 }
-#endif
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/Makefile linux/arch/arm/nwfpe/Makefile
--- v2.4.3/linux/arch/arm/nwfpe/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/nwfpe/Makefile	Wed Apr 11 19:02:27 2001
@@ -1,7 +1,7 @@
 #
 # linux/arch/arm/nwfpe/Makefile
 #
-# Copyright (C) 1998, 1999 Philip Blundell
+# Copyright (C) 1998, 1999, 2001 Philip Blundell
 #
 
 USE_STANDARD_AS_RULE := true
@@ -14,7 +14,7 @@
 
 list-multi		:= nwfpe.o
 
-obj-$(CONFIG_NWFPE)	+= nwfpe.o
+obj-$(CONFIG_FPE_NWFPE)	+= nwfpe.o
 
 nwfpe-objs		:= fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \
 			   fpmodule.o fpopcode.o softfloat.o \
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/config.h linux/arch/arm/nwfpe/config.h
--- v2.4.3/linux/arch/arm/nwfpe/config.h	Mon Aug 30 18:15:19 1999
+++ linux/arch/arm/nwfpe/config.h	Wed Dec 31 16:00:00 1969
@@ -1,31 +0,0 @@
-/*
-    NetWinder Floating Point Emulator
-    (c) Rebel.com, 1998-1999
-
-    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __CONFIG_H__
-#define __CONFIG_H__
-
-#if 1
-#define C_SYMBOL_NAME(foo)	foo
-#else
-#define C_SYMBOL_NAME(foo)	_##foo
-#endif
-
-#endif
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/double_cpdo.c linux/arch/arm/nwfpe/double_cpdo.c
--- v2.4.3/linux/arch/arm/nwfpe/double_cpdo.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/nwfpe/double_cpdo.c	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Rebel.com, 1998-1999
+    (c) Rebel.COM, 1998,1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -22,10 +22,6 @@
 #include "softfloat.h"
 #include "fpopcode.h"
 #include "fpa11.h"
-
-extern FPA11 *fpa11;
-
-float64 getDoubleConstant(unsigned int);
 
 float64 float64_exp(float64 Fm);
 float64 float64_ln(float64 Fm);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/entry.S linux/arch/arm/nwfpe/entry.S
--- v2.4.3/linux/arch/arm/nwfpe/entry.S	Wed Oct 20 16:29:08 1999
+++ linux/arch/arm/nwfpe/entry.S	Wed Apr 11 19:02:27 2001
@@ -1,7 +1,7 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
-    (c) Philip Blundell 1998-1999
+    (c) Rebel.COM, 1998
+    (c) 1998, 1999 Philip Blundell
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -86,7 +86,7 @@
 
         ldr r5, [r4, #60]	 	@ get contents of PC;
 	sub r8, r5, #4
-.Lx2:	ldrt r0, [r8], #0		@ get actual instruction into r0
+.Lx2:	ldrt r0, [r8]			@ get actual instruction into r0
 emulate:
 	bl EmulateAll			@ emulate the instruction
    	cmp r0, #0			@ was emulation successful
@@ -115,15 +115,17 @@
         mov r0, r6			@ prepare for EmulateAll()
    	b emulate			@ if r0 != 0, goto EmulateAll
 
-	@ We need to be prepared for the instruction at .Lx1 or .Lx2
-	@ to fault.
+	@ We need to be prepared for the instructions at .Lx1 and .Lx2 
+	@ to fault.  Emit the appropriate exception gunk to fix things up.
+	@ ??? For some reason, faults can happen at .Lx2 even with a
+	@ plain LDR instruction.  Weird, but it seems harmless.
 	.section .fixup,"ax"
-	.align
-.Lfix:	mov	pc, r9
+	.align	2
+.Lfix:	mov	pc, r9			@ let the user eat segfaults
 	.previous
 
 	.section __ex_table,"a"
-	.align 3
-	.long	.Lx2, .Lfix
+	.align	3
 	.long	.Lx1, .Lfix
+	.long	.Lx2, .Lfix
 	.previous
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/entry26.S linux/arch/arm/nwfpe/entry26.S
--- v2.4.3/linux/arch/arm/nwfpe/entry26.S	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/nwfpe/entry26.S	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.COM, 1998
     (c) Philip Blundell 1998-1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
@@ -84,7 +84,7 @@
 	beq	fpundefinstr		@ no, return failure
 
 next:
-	ldrt	r6, [r5], #4		@ get the next instruction and
+.Lx1:	ldrt	r6, [r5], #4		@ get the next instruction and
 					@ increment PC
 
 	and	r2, r6, #0x0F000000	@ test for FP insns
@@ -110,3 +110,13 @@
 	adr	lr, 1b
 	orr	lr, lr, #3
 	b	EmulateAll		@ if r0 != 0, goto EmulateAll
+
+.Lret:	b	ret_from_exception	@ let the user eat segfaults
+	
+	@ We need to be prepared for the instruction at .Lx1 to fault.
+	@ Emit the appropriate exception gunk to fix things up.
+	.section __ex_table,"a"
+	.align	3
+	.long	.Lx1
+	ldr	lr, [lr, $(.Lret - .Lx1)/4]
+	.previous
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/extended_cpdo.c linux/arch/arm/nwfpe/extended_cpdo.c
--- v2.4.3/linux/arch/arm/nwfpe/extended_cpdo.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/nwfpe/extended_cpdo.c	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Rebel.com, 1998-1999
+    (c) Rebel.COM, 1998,1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -22,8 +22,6 @@
 #include "softfloat.h"
 #include "fpopcode.h"
 #include "fpa11.h"
-
-floatx80 getExtendedConstant(unsigned int);
 
 floatx80 floatx80_exp(floatx80 Fm);
 floatx80 floatx80_ln(floatx80 Fm);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/fpa11.c linux/arch/arm/nwfpe/fpa11.c
--- v2.4.3/linux/arch/arm/nwfpe/fpa11.c	Wed Oct 20 16:29:08 1999
+++ linux/arch/arm/nwfpe/fpa11.c	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Rebel.com, 1998-1999
+    (c) Rebel.COM, 1998,1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -46,8 +46,8 @@
     fpa11->fType[i] = typeNone;
   }
   
-  /* FPSR: set system id to FP_EMULATOR, clear all other bits */
-  fpa11->fpsr = FP_EMULATOR;
+  /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
+  fpa11->fpsr = FP_EMULATOR | BIT_AC;
   
   /* FPCR: set SB, AB and DA bits, clear all others */
 #if MAINTAIN_FPCR
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/fpa11.inl linux/arch/arm/nwfpe/fpa11.inl
--- v2.4.3/linux/arch/arm/nwfpe/fpa11.inl	Wed Oct 20 16:29:08 1999
+++ linux/arch/arm/nwfpe/fpa11.inl	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.COM, 1998,1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/fpa11_cpdo.c linux/arch/arm/nwfpe/fpa11_cpdo.c
--- v2.4.3/linux/arch/arm/nwfpe/fpa11_cpdo.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/nwfpe/fpa11_cpdo.c	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Rebel.com, 1998-1999
+    (c) Rebel.COM, 1998,1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/fpa11_cprt.c linux/arch/arm/nwfpe/fpa11_cprt.c
--- v2.4.3/linux/arch/arm/nwfpe/fpa11_cprt.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/nwfpe/fpa11_cprt.c	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Rebel.com, 1998-1999
+    (c) Rebel.COM, 1998,1999
     (c) Philip Blundell, 1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/fpmodule.c linux/arch/arm/nwfpe/fpmodule.c
--- v2.4.3/linux/arch/arm/nwfpe/fpmodule.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/nwfpe/fpmodule.c	Wed Apr 11 19:02:27 2001
@@ -55,6 +55,8 @@
 #else
 #define fp_send_sig	send_sig
 #define kern_fp_enter	fp_enter
+
+extern char fpe_type[];
 #endif
 
 /* kernel function prototypes required */
@@ -72,24 +74,45 @@
 /* Address of user registers on the kernel stack. */
 unsigned int *userRegisters;
 
-int __init fpe_init(void)
+#ifdef MODULE
+/*
+ * Return 0 if we can be unloaded.  This can only happen if
+ * kern_fp_enter is still pointing at nwfpe_enter
+ */
+static int fpe_unload(void)
+{
+  return (kern_fp_enter == nwfpe_enter) ? 0 : 1;
+}
+#endif
+
+static int __init fpe_init(void)
 {
-  if (sizeof(FPA11) > sizeof(union fp_state))
+  if (sizeof(FPA11) > sizeof(union fp_state)) {
     printk(KERN_ERR "nwfpe: bad structure size\n");
-  else {
-    /* Display title, version and copyright information. */
-    printk(KERN_WARNING "NetWinder Floating Point Emulator V0.95 "
-	   "(c) 1998-1999 Rebel.com\n");
-
-    /* Save pointer to the old FP handler and then patch ourselves in */
-    orig_fp_enter = kern_fp_enter;
-    kern_fp_enter = nwfpe_enter;
+    return -EINVAL;
   }
 
+#ifdef MODULE
+  if (!mod_member_present(&__this_module, can_unload))
+    return -EINVAL;
+  __this_module.can_unload = fpe_unload;
+#else
+  if (fpe_type[0] && strcmp(fpe_type, "nwfpe"))
+    return 0;
+#endif
+
+  /* Display title, version and copyright information. */
+  printk(KERN_WARNING "NetWinder Floating Point Emulator V0.95 "
+	 "(c) 1998-1999 Rebel.com\n");
+
+  /* Save pointer to the old FP handler and then patch ourselves in */
+  orig_fp_enter = kern_fp_enter;
+  kern_fp_enter = nwfpe_enter;
+
   return 0;
 }
 
-void __exit fpe_exit(void)
+static void __exit fpe_exit(void)
 {
   /* Restore the values we saved earlier. */
   kern_fp_enter = orig_fp_enter;
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/fpmodule.inl linux/arch/arm/nwfpe/fpmodule.inl
--- v2.4.3/linux/arch/arm/nwfpe/fpmodule.inl	Wed Oct 20 16:29:08 1999
+++ linux/arch/arm/nwfpe/fpmodule.inl	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
-   NetWinder Floating Point Emulator
-   (c) Rebel.com, 1998-1999
+    NetWinder Floating Point Emulator
+    (c) Rebel.COM, 1998,1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/fpopcode.c linux/arch/arm/nwfpe/fpopcode.c
--- v2.4.3/linux/arch/arm/nwfpe/fpopcode.c	Wed Oct 20 16:29:08 1999
+++ linux/arch/arm/nwfpe/fpopcode.c	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Rebel.com, 1998-1999
+    (c) Rebel.COM, 1998,1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -26,7 +26,7 @@
 #include "fpmodule.h"
 #include "fpmodule.inl"
 
-static floatx80 floatx80Constant[] = {
+const floatx80 floatx80Constant[] = {
   { 0x0000, 0x0000000000000000ULL},	/* extended 0.0 */
   { 0x3fff, 0x8000000000000000ULL},	/* extended 1.0 */
   { 0x4000, 0x8000000000000000ULL},	/* extended 2.0 */
@@ -37,7 +37,7 @@
   { 0x4002, 0xa000000000000000ULL}	/* extended 10.0 */
 };  
 
-static float64 float64Constant[] = {
+const float64 float64Constant[] = {
   0x0000000000000000ULL,		/* double 0.0 */
   0x3ff0000000000000ULL,		/* double 1.0 */
   0x4000000000000000ULL,		/* double 2.0 */
@@ -48,7 +48,7 @@
   0x4024000000000000ULL			/* double 10.0 */
 };  
 
-static float32 float32Constant[] = {
+const float32 float32Constant[] = {
   0x00000000,				/* single 0.0 */
   0x3f800000,				/* single 1.0 */
   0x40000000,				/* single 2.0 */
@@ -59,21 +59,6 @@
   0x41200000				/* single 10.0 */
 };  
 
-floatx80 getExtendedConstant(const unsigned int nIndex)
-{
-   return floatx80Constant[nIndex];
-} 
-
-float64 getDoubleConstant(const unsigned int nIndex)
-{
-   return float64Constant[nIndex];
-} 
-
-float32 getSingleConstant(const unsigned int nIndex)
-{
-   return float32Constant[nIndex];
-} 
-
 unsigned int getTransferLength(const unsigned int opcode)
 {
   unsigned int nRc;
@@ -135,10 +120,10 @@
   return(nRc);
 }
 
-/* contition code lookup table
+/* condition code lookup table
  index into the table is test code: EQ, NE, ... LT, GT, AL, NV
  bit position in short is condition code: NZCV */
-unsigned short aCC[16] = {
+static const unsigned short aCC[16] = {
     0xF0F0, // EQ == Z set
     0x0F0F, // NE
     0xCCCC, // CS == C set
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/fpopcode.h linux/arch/arm/nwfpe/fpopcode.h
--- v2.4.3/linux/arch/arm/nwfpe/fpopcode.h	Mon Aug 30 18:15:19 1999
+++ linux/arch/arm/nwfpe/fpopcode.h	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Rebel.com, 1998-1999
+    (c) Rebel.COM, 1998,1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -366,11 +366,25 @@
 /* Get the rounding mode from the opcode. */
 #define getRoundingMode(opcode)		((opcode & MASK_ROUNDING_MODE) >> 5)
 
-float32 getSingleConstant(const unsigned int nIndex);
-float64 getDoubleConstant(const unsigned int nIndex);
-floatx80 getExtendedConstant(const unsigned int nIndex);
+static inline const floatx80 getExtendedConstant(const unsigned int nIndex)
+{
+   extern const floatx80 floatx80Constant[];
+   return floatx80Constant[nIndex];
+} 
+
+static inline const float64 getDoubleConstant(const unsigned int nIndex)
+{
+   extern const float64 float64Constant[];
+   return float64Constant[nIndex];
+} 
+
+static inline const float32 getSingleConstant(const unsigned int nIndex)
+{
+   extern const float32 float32Constant[];
+   return float32Constant[nIndex];
+} 
 
-unsigned int getRegisterCount(const unsigned int opcode);
-unsigned int getDestinationSize(const unsigned int opcode);
+extern unsigned int getRegisterCount(const unsigned int opcode);
+extern unsigned int getDestinationSize(const unsigned int opcode);
 
 #endif
diff -u --recursive --new-file v2.4.3/linux/arch/arm/nwfpe/single_cpdo.c linux/arch/arm/nwfpe/single_cpdo.c
--- v2.4.3/linux/arch/arm/nwfpe/single_cpdo.c	Wed Oct 20 16:29:08 1999
+++ linux/arch/arm/nwfpe/single_cpdo.c	Wed Apr 11 19:02:27 2001
@@ -1,6 +1,6 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Rebel.com, 1998-1999
+    (c) Rebel.COM, 1998,1999
 
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
@@ -22,8 +22,6 @@
 #include "softfloat.h"
 #include "fpopcode.h"
 #include "fpa11.h"
-
-float32 getSingleConstant(unsigned int);
 
 float32 float32_exp(float32 Fm);
 float32 float32_ln(float32 Fm);
diff -u --recursive --new-file v2.4.3/linux/arch/arm/tools/getconstants.c linux/arch/arm/tools/getconstants.c
--- v2.4.3/linux/arch/arm/tools/getconstants.c	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/tools/getconstants.c	Wed Apr 11 19:02:27 2001
@@ -14,14 +14,8 @@
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 
-/*
- * Make sure that the compiler and target are compatible
- */
-#if (defined(__APCS_32__) && defined(CONFIG_CPU_26))
-#error Your compiler targets APCS-32 but this kernel requires APCS-26.
-#endif
-#if (defined(__APCS_26__) && defined(CONFIG_CPU_32))
-#error Your compiler targets APCS-26 but this kernel requires APCS-32.
+#ifndef __APCS_32__
+#error APCS-32 required
 #endif
 
 #define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n)
diff -u --recursive --new-file v2.4.3/linux/arch/arm/tools/mach-types linux/arch/arm/tools/mach-types
--- v2.4.3/linux/arch/arm/tools/mach-types	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/tools/mach-types	Wed Apr 11 19:02:27 2001
@@ -1,10 +1,12 @@
 # Database of machine macros and numbers
 #
+# This file is linux/arch/arm/tools/mach-types
+#
 # Please do not send patches to this file; it is automatically generated!
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Fri Feb  9 22:27:32 2001
+# Last update: Sat Apr 7 09:45:09 2001
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -35,7 +37,7 @@
 assabet			SA1100_ASSABET		ASSABET			25
 victor			SA1100_VICTOR		VICTOR			26
 lart			SA1100_LART		LART			27
-ranger			ARCH_RANGER		RANGER			28
+ranger			SA1100_RANGER		RANGER			28
 graphicsclient		SA1100_GRAPHICSCLIENT	GRAPHICSCLIENT		29
 xp860			SA1100_XP860		XP860			30
 cerf			SA1100_CERF		CERF			31
@@ -48,7 +50,7 @@
 netport			SA1100_NETPORT		NETPORT			38
 pangolin		SA1100_PANGOLIN		PANGOLIN		39
 yopy			SA1100_YOPY		YOPY			40
-coolidge		SA1100_COOLIDGE		coolidge		41
+coolidge		SA1100_COOLIDGE		COOLIDGE		41
 huw_webpanel		SA1100_HUW_WEBPANEL	HUW_WEBPANEL		42
 spotme			ARCH_SPOTME		SPOTME			43
 freebird		ARCH_FREEBIRD		FREEBIRD		44
@@ -65,6 +67,16 @@
 webpal			ARCH_WEBPAL		WEBPAL			55
 linpda			SA1100_LINPDA		LINPDA			56
 anakin			ARCH_ANAKIN		ANAKIN			57
+mvi			SA1100_MVI		MVI			58
+jupiter			SA1100_JUPITER		JUPITER			59
+psionw			ARCH_PSIONW		PSIONW			60
+aln			SA1100_ALN		ALN			61
+camelot			ARCH_CAMELOT		CAMELOT			62
+gds2200			SA1100_GDS2200		GDS2200			63
+psion_series7		SA1100_PSION_SERIES7	PSION_SERIES7		64
+xfile			SA1100_XFILE		XFILE			65
+accelent_ep9312		ARCH_ACCELENT_EP9312	ACCELENT_EP9312		66
+ic200			ARCH_IC200		IC200			67
 
 # The following are unallocated
 empeg			SA1100_EMPEG		EMPEG
diff -u --recursive --new-file v2.4.3/linux/arch/cris/Makefile linux/arch/cris/Makefile
--- v2.4.3/linux/arch/cris/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/Makefile	Fri Apr  6 10:42:55 2001
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.11 2000/11/27 17:58:30 bjornw Exp $
+# $Id: Makefile,v 1.15 2001/02/16 17:50:04 larsv Exp $
 # cris/Makefile
 #
 # This file is included by the global makefile so that you can add your own
@@ -25,7 +25,7 @@
 # regenerating stuff (even for incremental linking of subsystems!) is
 # even more nauseating.
 LD = if [ ! -e $(LD_SCRIPT).tmp -o $(LD_SCRIPT) -nt $(LD_SCRIPT).tmp ]; then \
-          sed -e s/@ETRAX_DRAM_BASE@/0x$(ETRAX_DRAM_BASE)/ \
+          sed -e s/@ETRAX_DRAM_VIRTUAL_BASE@/0x$(ETRAX_DRAM_VIRTUAL_BASE)/ \
               -e s/@ETRAX_DRAM_SIZE_M@/$(ETRAX_DRAM_SIZE)/ \
               < $(LD_SCRIPT) > $(LD_SCRIPT).tmp; \
      else true; \
@@ -49,7 +49,7 @@
 
 HEAD := arch/cris/kernel/head.o
 
-SUBDIRS += arch/cris/kernel arch/cris/mm arch/cris/lib arch/cris/drivers
+SUBDIRS += arch/cris/kernel arch/cris/mm arch/cris/lib arch/cris/drivers arch/cris/boot/rescue
 CORE_FILES += arch/cris/kernel/kernel.o arch/cris/mm/mm.o arch/cris/drivers/drivers.o
 LIBGCC = $(shell $(CC) $(CFLAGS) -print-file-name=libgcc.a)
 LIBS := $(TOPDIR)/arch/cris/lib/lib.a $(LIBS) $(TOPDIR)/arch/cris/lib/lib.a $(LIBGCC)
@@ -76,10 +76,18 @@
 
 cramfs:
 ## cramfs      - Creates a cramfs image
-	mkcramfs -p 8192 root cramfs.img
+	mkcramfs -b 8192 root cramfs.img
 	cat vmlinux.bin cramfs.img >timage
 
-zImage: vmlinux
+clinux: vmlinux.bin decompress.bin rescue.bin
+
+decompress.bin: dummy
+	@make -C arch/cris/boot/compressed decompress.bin
+
+rescue.bin: dummy
+	@make -C arch/cris/boot/rescue rescue.bin
+
+zImage: vmlinux.bin
 ## zImage     - Compressed kernel (gzip)
 	@$(MAKEBOOT) zImage
 
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/compressed/Makefile linux/arch/cris/boot/compressed/Makefile
--- v2.4.3/linux/arch/cris/boot/compressed/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/boot/compressed/Makefile	Fri Apr  6 10:42:55 2001
@@ -16,11 +16,14 @@
 
 all: vmlinuz
 
-vmlinuz: piggy.img $(OBJECTS)
-	$(LD) -mcriself -T decompress.ld -o decompress.o $(OBJECTS)
+decompress.bin: $(OBJECTS)
+	$(LD) -T decompress.ld -o decompress.o $(OBJECTS)
 	$(OBJCOPY) -O binary --remove-section=.bss decompress.o decompress.bin
 # save it for mkprod in the topdir.
 	cp decompress.bin $(TOPDIR)
+
+
+vmlinuz: piggy.img decompress.bin
 	cat decompress.bin piggy.img $(TOPDIR)/cramfs.img > vmlinuz
 	rm -f piggy.img
 
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/compressed/decompress.ld linux/arch/cris/boot/compressed/decompress.ld
--- v2.4.3/linux/arch/cris/boot/compressed/decompress.ld	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/boot/compressed/decompress.ld	Fri Apr  6 10:42:55 2001
@@ -1,3 +1,5 @@
+OUTPUT_FORMAT(elf32-us-cris)
+
 MEMORY 
 	{
 	dram : ORIGIN = 0x40700000,
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/compressed/head.S linux/arch/cris/boot/compressed/head.S
--- v2.4.3/linux/arch/cris/boot/compressed/head.S	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/boot/compressed/head.S	Fri Apr  6 10:42:55 2001
@@ -8,7 +8,6 @@
  *
  */
 
-#include <linux/config.h>
 #define ASSEMBLER_MACROS_ONLY
 #include <asm/sv_addr_ag.h>
 
@@ -22,23 +21,24 @@
 	nop
 	di
 
-#ifndef CONFIG_SVINTO_SIM	
-
-	;; We need to setup the bus registers before we start using the DRAM
+	;; We need to initialze DRAM registers before we start using the DRAM
+#include "../../lib/dram_init.S"
+	
+dram_init_finished:
+	
+	;; Initiate the PA and PB ports
 
-	move.d   DEF_R_WAITSTATES, r0
-	move.d   r0, [R_WAITSTATES]
+	move.b   DEF_R_PORT_PA_DATA, r0
+	move.b   r0, [R_PORT_PA_DATA]
 
-	move.d   DEF_R_BUS_CONFIG, r0
-	move.d   r0, [R_BUS_CONFIG]
-  
-	move.d   DEF_R_DRAM_CONFIG, r0
-	move.d   r0, [R_DRAM_CONFIG]
+	move.b   DEF_R_PORT_PA_DIR, r0
+	move.b   r0, [R_PORT_PA_DIR]
 
-	move.d   DEF_R_DRAM_TIMING, r0
-	move.d   r0, [R_DRAM_TIMING]
+	move.b   DEF_R_PORT_PB_DATA, r0
+	move.b   r0, [R_PORT_PB_DATA]
 
-#endif
+	move.b   DEF_R_PORT_PB_DIR, r0
+	move.b   r0, [R_PORT_PB_DIR]
 
 	;; Setup the stack to a suitably high address.
 	;; We assume 8 MB is the minimum DRAM in an eLinux
@@ -83,7 +83,7 @@
 	;; Do the decompression and save compressed size in _inptr
 	
 	jsr	_decompress_kernel
-
+	
 	;; Put start address of cramfs in r9 so the kernel can use it
 	;; when mounting from flash
 
@@ -91,7 +91,6 @@
 	add.d	[_inptr], r9		; size of compressed kernel
 
 	;; Enter the decompressed kernel
-		
 	jump	0x40004000	; kernel is linked to this address
 	
 	.data
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/compressed/misc.c linux/arch/cris/boot/compressed/misc.c
--- v2.4.3/linux/arch/cris/boot/compressed/misc.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/cris/boot/compressed/misc.c	Fri Apr  6 10:42:55 2001
@@ -13,7 +13,7 @@
  */
 
 /* where the piggybacked kernel image expects itself to live.
- * it is the same address we use when we network load an uncompressed
+ * it is the same adress we use when we network load an uncompressed
  * image into DRAM, and it is the address the kernel is linked to live
  * at by etrax100.ld.
  */
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/rescue/Makefile linux/arch/cris/boot/rescue/Makefile
--- v2.4.3/linux/arch/cris/boot/rescue/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/rescue/Makefile	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,50 @@
+#
+# Makefile for rescue code
+#
+ifndef TOPDIR
+TOPDIR = ../../../..
+endif
+CC = gcc-cris -I $(TOPDIR)/include
+CFLAGS = -O2
+LD = ld-cris
+OBJCOPY = objcopy-cris
+
+all: rescue.bin testrescue.bin kimagerescue.bin
+
+rescue: rescue.bin
+	# do nothing
+
+rescue.bin: head.o
+	$(LD) -T rescue.ld -o rescue.o head.o
+	$(OBJCOPY) -O binary --remove-section=.bss rescue.o rescue.bin
+	cp rescue.bin $(TOPDIR)
+
+testrescue.bin: testrescue.o
+	$(OBJCOPY) -O binary --remove-section=.bss testrescue.o tr.bin
+# Pad it to 784 bytes
+	dd if=/dev/zero of=tmp2423 bs=1 count=784
+	cat tr.bin tmp2423 >testrescue_tmp.bin
+	dd if=testrescue_tmp.bin of=testrescue.bin bs=1 count=784
+	rm tr.bin tmp2423 testrescue_tmp.bin
+
+kimagerescue.bin: kimagerescue.o
+	$(OBJCOPY) -O binary --remove-section=.bss kimagerescue.o ktr.bin
+# Pad it to 784 bytes, that's what the rescue loader expects
+	dd if=/dev/zero of=tmp2423 bs=1 count=784
+	cat ktr.bin tmp2423 >kimagerescue_tmp.bin
+	dd if=kimagerescue_tmp.bin of=kimagerescue.bin bs=1 count=784
+	rm ktr.bin tmp2423 kimagerescue_tmp.bin
+
+head.o: head.S
+	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+
+testrescue.o: testrescue.S
+	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+
+kimagerescue.o: kimagerescue.S
+	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+
+clean:
+	rm -f *.o *.bin
+
+fastdep:
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/rescue/head.S linux/arch/cris/boot/rescue/head.S
--- v2.4.3/linux/arch/cris/boot/rescue/head.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/rescue/head.S	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,323 @@
+	;; $Id: head.S,v 1.3 2001/02/14 16:57:25 larsv Exp $
+	;; 
+	;; Rescue code, made to reside at the beginning of the
+	;; flash-memory. when it starts, it checks a partition
+	;; table at the first sector after the rescue sector.
+	;; the partition table was generated by the product builder
+	;; script and contains offsets, lengths, types and checksums
+	;; for each partition that this code should check.
+	;;
+	;; If any of the checksums fail, we assume the flash is so
+	;; corrupt that we cant use it to boot into the ftp flash
+	;; loader, and instead we initialize the serial port to
+	;; receive a flash-loader and new flash image. we dont include
+	;; any flash code here, but just accept a certain amount of
+	;; bytes from the serial port and jump into it. the downloaded
+	;; code is put in the cache.
+	;;
+	;; The partitiontable is designed so that it is transparent to
+	;; code execution - it has a relative branch opcode in the
+	;; beginning that jumps over it. each entry contains extra
+	;; data so we can add stuff later.
+	;;
+	;; Partition table format:
+	;;
+	;;     Code transparency:
+	;; 
+	;;     2 bytes    [opcode 'nop']
+	;;     2 bytes    [opcode 'di']
+	;;     4 bytes    [opcode 'ba <offset>', 8-bit or 16-bit version]
+	;;     2 bytes    [opcode 'nop', delay slot]
+	;;
+	;;     Table validation (at +10):	
+	;; 
+	;;     2 bytes    [magic/version word for partitiontable - 0xef, 0xbe]
+	;;     2 bytes    [length of all entries plus the end marker]
+	;;     4 bytes    [checksum for the partitiontable itself]
+	;;
+	;;     Entries, each with the following format, last has offset -1:	
+	;;    
+	;;        4 bytes    [offset in bytes, from start of flash]
+	;;        4 bytes    [length in bytes of partition]
+	;;        4 bytes    [checksum, simple longword sum]
+	;;        2 bytes    [partition type]
+	;;        2 bytes    [flags, only bit 0 used, ro/rw = 1/0]
+	;;        16 bytes   [reserved for future use]
+	;;
+	;;     End marker
+	;;
+	;;        4 bytes    [-1]
+	;; 
+	;;	 10 bytes    [0, padding]
+	;; 
+	;; Bit 0 in flags signifies RW or RO. The rescue code only bothers
+	;; to check the checksum for RO partitions, since the others will
+	;; change its data without updating the checksums. A 1 in bit 0
+	;; means RO, 0 means RW. That way, it is possible to set a partition
+	;; in RO mode initially, and later mark it as RW, since you can always
+	;; write 0's to the flash.
+	;;
+	;; During the wait for serial input, the status LED will flash so the
+	;; user knows something went wrong.
+	;; 
+	;; Copyright (C) 1999 Axis Communications AB
+
+#include <linux/config.h>
+#define ASSEMBLER_MACROS_ONLY
+#include <asm/sv_addr_ag.h>
+
+	;; The partitiontable is looked for at the first sector after the boot
+	;; sector. Sector size is 65536 bytes in all flashes we use.
+		
+#define PTABLE_START 0x10000
+#define PTABLE_MAGIC 0xbeef
+
+	;; The normal Etrax100 on-chip boot ROM does serial boot at 0x380000f0.
+	;; That is not where we put our downloaded serial boot-code. The length is
+	;; enough for downloading code that loads the rest of itself (after
+	;; having setup the DRAM etc). It is the same length as the on-chip
+	;; ROM loads, so the same host loader can be used to load a rescued
+	;; product as well as one booted through the Etrax serial boot code.
+		
+#define CODE_START 0x40000000
+#define CODE_LENGTH 784
+
+#ifdef CONFIG_RESCUE_SER0
+#define SERXOFF R_SERIAL0_XOFF
+#define SERBAUD R_SERIAL0_BAUD
+#define SERRECC R_SERIAL0_REC_CTRL
+#define SERRDAT R_SERIAL0_REC_DATA
+#define SERSTAT R_SERIAL0_STATUS
+#endif
+#ifdef CONFIG_RESCUE_SER1
+#define SERXOFF R_SERIAL1_XOFF
+#define SERBAUD R_SERIAL1_BAUD
+#define SERRECC R_SERIAL1_REC_CTRL
+#define SERRDAT R_SERIAL1_REC_DATA
+#define SERSTAT R_SERIAL1_STATUS
+#endif
+#ifdef CONFIG_RESCUE_SER2
+#define SERXOFF R_SERIAL2_XOFF
+#define SERBAUD R_SERIAL2_BAUD
+#define SERRECC R_SERIAL2_REC_CTRL
+#define SERRDAT R_SERIAL2_REC_DATA
+#define SERSTAT R_SERIAL2_STATUS
+#endif	
+#ifdef CONFIG_RESCUE_SER3
+#define SERXOFF R_SERIAL3_XOFF
+#define SERBAUD R_SERIAL3_BAUD
+#define SERRECC R_SERIAL3_REC_CTRL
+#define SERRDAT R_SERIAL3_REC_DATA
+#define SERSTAT R_SERIAL3_STATUS
+#endif
+
+#define NOP_DI 0xf025050f
+	
+	.text
+	
+	;; This is the entry point of the rescue code
+	;; 0x80000000 if loaded in flash (as it should be)
+	;; since etrax actually starts at address 2 when booting from flash, we
+	;; put a nop (2 bytes) here first so we dont accidentally skip the di
+	
+	nop	
+	di
+
+	jump	in_cache	; enter cached area instead
+in_cache:	
+
+	;; first put a jump test to give a possibility of upgrading the rescue code
+	;; without erasing/reflashing the sector. we put a longword of -1 here and if
+	;; its not -1, we jump using the value as jump target. since we can always
+	;; change 1's to 0's without erasing the sector, it is possible to add new
+	;; code after this and altering the jumptarget in an upgrade.
+
+jtcd:	move.d	[jumptarget], r0
+	cmp.d	0xffffffff, r0
+	beq	no_newjump
+	nop
+	
+	jump	[r0]
+
+jumptarget:	
+	.dword	0xffffffff	; can be overwritten later to insert new code
+	
+no_newjump:	
+	;; We need to setup the bus registers before we start using the DRAM
+#include "../../lib/dram_init.S"
+
+	;; we now should go through the checksum-table and check the listed
+	;; partitions for errors.
+	
+	move.d	PTABLE_START, r3
+	move.d	[r3], r0
+	cmp.d	NOP_DI, r0	; make sure the nop/di is there...
+	bne	do_rescue
+	nop
+	
+	;; skip the code transparency block (10 bytes).
+
+	addq	10, r3
+	
+	;; check for correct magic
+	
+	move.w	[r3+], r0
+	cmp.w	PTABLE_MAGIC, r0
+	bne	do_rescue	; didn't recognize - trig rescue
+	nop
+
+	;; check for correct ptable checksum
+
+	movu.w	[r3+], r2	; ptable length
+	move.d	r2, r8		; save for later, length of total ptable
+	addq	28, r8		; account for the rest
+	move.d	[r3+], r4	; ptable checksum
+	move.d	r3, r1
+	jsr	checksum	; r1 source, r2 length, returns in r0
+
+	cmp.d	r0, r4
+	bne	do_rescue	; didn't match - trig rescue
+	nop
+	
+	;; ptable is ok. validate each entry.
+
+	moveq	-1, r7
+	
+ploop:	move.d	[r3+], r1	; partition offset (from ptable start)
+	bne	notfirst	; check if its the partition containing ptable
+	nop			; yes..
+	move.d	r8, r1		; for its checksum check, skip the ptable
+	move.d	[r3+], r2	; partition length
+	sub.d	r8, r2		; minus the ptable length
+	ba	bosse
+	nop
+notfirst:	
+	cmp.d	-1, r1		; the end of the ptable ?
+	beq	flash_ok	;   if so, the flash is validated
+	move.d	[r3+], r2	; partition length
+bosse:	move.d	[r3+], r5	; checksum
+	move.d	[r3+], r4	; type and flags
+	addq	16, r3		; skip the reserved bytes
+	btstq	16, r4		; check ro flag
+	bpl	ploop		;   rw partition, skip validation
+	nop
+	btstq	17, r4		; check bootable flag
+	bpl	1f
+	nop
+	move.d	r1, r7		; remember boot partition offset
+1:	
+
+	add.d	PTABLE_START, r1
+	
+	jsr	checksum	; checksum the partition
+	
+	cmp.d	r0, r5
+	beq	ploop		; checksums matched, go to next entry
+	nop
+
+	;; otherwise fall through to the rescue code.
+	
+do_rescue:
+	;; setup port PA and PB default initial directions and data
+	;; (so we can flash LEDs, and so that DTR and others are set)
+	
+	move.b	DEF_R_PORT_PA_DIR, r0
+	move.b	r0, [R_PORT_PA_DIR]
+	move.b	DEF_R_PORT_PA_DATA, r0
+	move.b	r0, [R_PORT_PA_DATA]
+	
+	move.b	DEF_R_PORT_PB_DIR, r0
+	move.b	r0, [R_PORT_PB_DIR]
+	move.b	DEF_R_PORT_PB_DATA, r0
+	move.b	r0, [R_PORT_PB_DATA]
+
+	;; setup the serial port at 115200 baud
+	
+	moveq	0, r0
+	move.d	r0, [SERXOFF] 
+
+	move.b	0x99, r0
+	move.b	r0, [SERBAUD]		; 115.2kbaud for both transmit and receive
+
+	move.b	0x40, r0		; rec enable
+	move.b	r0, [SERRECC] 
+
+	moveq	0, r1		; "timer" to clock out a LED red flash
+	move.d	CODE_START, r3	; destination counter
+	movu.w	CODE_LENGTH, r4	; length
+	
+wait_ser:
+	addq	1, r1
+#ifndef CONFIG_ETRAX_NO_LEDS
+#ifdef CONFIG_ETRAX_PA_LEDS
+	move.b	DEF_R_PORT_PA_DATA, r2
+#endif
+#ifdef CONFIG_ETRAX_PB_LEDS
+	move.b	DEF_R_PORT_PB_DATA, r2
+#endif
+	move.d	(1 << CONFIG_ETRAX_LED1R) | (1 << CONFIG_ETRAX_LED2R), r0
+	btstq	16, r1
+	bpl	1f
+	nop
+	or.d	r0, r2		; set bit
+	ba	2f
+	nop
+1:	not	r0		; clear bit
+	and.d	r0, r2
+2:	
+#ifdef CONFIG_ETRAX_PA_LEDS
+	move.b	r2, [R_PORT_PA_DATA]	
+#endif	
+#ifdef CONFIG_ETRAX_PB_LEDS
+	move.b	r2, [R_PORT_PB_DATA]	
+#endif
+#ifdef CONFIG_ETRAX_90000000_LEDS
+	move.b	r2, [0x90000000]
+#endif
+#endif
+	
+	;; check if we got something on the serial port
+	
+	move.b	[SERSTAT], r0
+	btstq	0, r0		; data_avail
+	bpl	wait_ser
+	nop
+
+	;; got something - copy the byte and loop
+
+	move.b	[SERRDAT], r0
+	move.b	r0, [r3+]
+	
+	subq	1, r4		; decrease length
+	bne	wait_ser
+	nop
+
+	;; jump into downloaded code
+	
+	jump	CODE_START
+
+flash_ok:
+	;; check r7, which contains either -1 or the partition to boot from
+
+	cmp.d	-1, r7
+	bne	1f
+	nop
+	move.d	PTABLE_START, r7; otherwise use the ptable start
+1:	
+	jump	r7		; boot!
+
+
+	;; Helper subroutines
+
+	;; Will checksum by simple addition
+	;; r1 - source
+	;; r2 - length in bytes
+	;; result will be in r0
+checksum:
+	moveq	0, r0
+1:	addu.b	[r1+], r0
+	subq	1, r2
+	bne	1b
+	nop
+	ret
+	nop
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/rescue/kimagerescue.S linux/arch/cris/boot/rescue/kimagerescue.S
--- v2.4.3/linux/arch/cris/boot/rescue/kimagerescue.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/rescue/kimagerescue.S	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,143 @@
+	;; $Id: kimagerescue.S,v 1.2 2001/02/14 16:57:25 larsv Exp $
+	;; 
+	;; Rescue code to be prepended on a kimage and copied to the
+	;; rescue serial port.
+	;; This is called from the rescue code, it will copy received data to
+	;; 4000500 and after a timeout jump to it.
+	
+#include <linux/config.h>
+#define ASSEMBLER_MACROS_ONLY
+#include <asm/sv_addr_ag.h>
+
+#define CODE_START 0x40000500
+#define CODE_LENGTH 784
+#define TIMEOUT_VALUE 1000
+	
+		
+#ifdef CONFIG_RESCUE_SER0
+#define SERXOFF R_SERIAL0_XOFF
+#define SERBAUD R_SERIAL0_BAUD
+#define SERRECC R_SERIAL0_REC_CTRL
+#define SERRDAT R_SERIAL0_REC_DATA
+#define SERSTAT R_SERIAL0_STATUS
+#endif
+#ifdef CONFIG_RESCUE_SER1
+#define SERXOFF R_SERIAL1_XOFF
+#define SERBAUD R_SERIAL1_BAUD
+#define SERRECC R_SERIAL1_REC_CTRL
+#define SERRDAT R_SERIAL1_REC_DATA
+#define SERSTAT R_SERIAL1_STATUS
+#endif
+#ifdef CONFIG_RESCUE_SER2
+#define SERXOFF R_SERIAL2_XOFF
+#define SERBAUD R_SERIAL2_BAUD
+#define SERRECC R_SERIAL2_REC_CTRL
+#define SERRDAT R_SERIAL2_REC_DATA
+#define SERSTAT R_SERIAL2_STATUS
+#endif	
+#ifdef CONFIG_RESCUE_SER3
+#define SERXOFF R_SERIAL3_XOFF
+#define SERBAUD R_SERIAL3_BAUD
+#define SERRECC R_SERIAL3_REC_CTRL
+#define SERRDAT R_SERIAL3_REC_DATA
+#define SERSTAT R_SERIAL3_STATUS
+#endif
+
+	.text
+	;; This is the entry point of the rescue code
+	;; 0x80000000 if loaded in flash (as it should be)
+	;; since etrax actually starts at address 2 when booting from flash, we
+	;; put a nop (2 bytes) here first so we dont accidentally skip the di
+	
+	nop	
+	di
+#ifndef CONFIG_SVINTO_SIM	
+	;; setup port PA and PB default initial directions and data
+	;; (so we can flash LEDs, and so that DTR and others are set)
+	
+	move.b	DEF_R_PORT_PA_DIR, r0
+	move.b	r0, [R_PORT_PA_DIR]
+	move.b	DEF_R_PORT_PA_DATA, r0
+	move.b	r0, [R_PORT_PA_DATA]
+	
+	move.b	DEF_R_PORT_PB_DIR, r0
+	move.b	r0, [R_PORT_PB_DIR]
+	move.b	DEF_R_PORT_PB_DATA, r0
+	move.b	r0, [R_PORT_PB_DATA]
+	
+	;; We need to setup the bus registers before we start using the DRAM
+#include "../../lib/dram_init.S"
+	
+#endif
+	;; Setup the stack to a suitably high address.
+	;; We assume 8 MB is the minimum DRAM in an eLinux
+	;; product and put the sp at the top for now.
+
+	move.d	0x40800000, sp
+	
+	;; setup the serial port at 115200 baud
+	
+	moveq	0, r0
+	move.d	r0, [SERXOFF] 
+
+	move.b	0x99, r0
+	move.b	r0, [SERBAUD]		; 115.2kbaud for both transmit and receive
+
+	move.b	0x40, r0		; rec enable
+	move.b	r0, [SERRECC] 
+
+
+	moveq	0, r1		; "timer" to clock out a LED red flash
+	move.d	CODE_START, r3	; destination counter
+	move.d	CODE_LENGTH, r4	; length
+	move.d	TIMEOUT_VALUE, r5	; "timeout" until jump
+
+wait_ser:
+	addq	1, r1
+	subq	1, r5		; decrease timeout
+	beq	jump_start	; timed out
+	nop
+#ifndef CONFIG_ETRAX_NO_LEDS
+#ifdef CONFIG_ETRAX_PA_LEDS
+	move.b	DEF_R_PORT_PA_DATA, r2
+#endif
+#ifdef CONFIG_ETRAX_PB_LEDS
+	move.b	DEF_R_PORT_PB_DATA, r2
+#endif
+	move.d	(1 << CONFIG_ETRAX_LED1R) | (1 << CONFIG_ETRAX_LED2R), r0
+	btstq	16, r1
+	bpl	1f
+	nop
+	or.d	r0, r2		; set bit
+	ba	2f
+	nop
+1:	not	r0		; clear bit
+	and.d	r0, r2
+2:	
+#ifdef CONFIG_ETRAX_PA_LEDS
+	move.b	r2, [R_PORT_PA_DATA]
+#endif	
+#ifdef CONFIG_ETRAX_PB_LEDS
+	move.b	r2, [R_PORT_PB_DATA]
+#endif
+#endif
+		
+	;; check if we got something on the serial port
+	
+	move.b	[SERSTAT], r0
+	btstq	0, r0		; data_avail
+	bpl	wait_ser
+	nop
+
+	;; got something - copy the byte and loop
+
+	move.b	[SERRDAT], r0
+	move.b	r0, [r3+]
+	move.d	TIMEOUT_VALUE, r5	; reset "timeout"
+	subq	1, r4		; decrease length
+	bne	wait_ser
+	nop
+jump_start:
+	;; jump into downloaded code
+
+	jump	CODE_START
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/rescue/rescue.ld linux/arch/cris/boot/rescue/rescue.ld
--- v2.4.3/linux/arch/cris/boot/rescue/rescue.ld	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/rescue/rescue.ld	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,20 @@
+MEMORY 
+	{
+	flash : ORIGIN = 0x00000000,
+	        LENGTH = 0x00100000
+	}
+
+SECTIONS
+{
+	.text :
+	{
+		_stext = . ;
+		*(.text)
+		_etext = . ;
+	} > flash
+	.data :
+	{
+		*(.data)
+		_edata = . ;
+	} > flash
+}
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/rescue/testrescue.S linux/arch/cris/boot/rescue/testrescue.S
--- v2.4.3/linux/arch/cris/boot/rescue/testrescue.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/rescue/testrescue.S	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,25 @@
+	;; $Id: testrescue.S,v 1.1 2001/01/31 15:32:09 johana Exp $
+	;;
+	;; Simple testcode to download by the rescue block.
+	;; Just lits some LEDs to show it was downloaded correctly.
+	;; 
+	;; Copyright (C) 1999 Axis Communications AB
+
+#define ASSEMBLER_MACROS_ONLY
+#include <asm/sv_addr_ag.h>
+
+	.text
+
+	nop
+	nop
+	moveq	-1, r2
+	move.b	r2, [R_PORT_PA_DIR]
+	moveq	0, r2
+	move.b	r2, [R_PORT_PA_DATA]	
+
+endless:
+	nop
+	ba	endless
+	nop
+
+	
diff -u --recursive --new-file v2.4.3/linux/arch/cris/boot/tools/build.c linux/arch/cris/boot/tools/build.c
--- v2.4.3/linux/arch/cris/boot/tools/build.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/tools/build.c	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,288 @@
+/*
+ *  linux/tools/build.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * This file builds a disk-image from three different files:
+ *
+ * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ * - setup: 8086 machine code, sets up system parm
+ * - system: 80386 code for actual system
+ *
+ * It does some checking that all files are of the correct type, and
+ * just writes the result to stdout, removing headers and padding to
+ * the right amount. It also writes some system data to stderr.
+ */
+
+/*
+ * Changes by tytso to allow root device specification
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ * Cross compiling fixes by Gertjan van Wingerde, July 1996
+ */
+
+#include <stdio.h>	/* fprintf */
+#include <string.h>
+#include <stdlib.h>	/* contains exit */
+#include <sys/types.h>	/* unistd.h needs this */
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>	/* contains read/write */
+#include <fcntl.h>
+#include <linux/a.out.h>
+#include <errno.h>
+
+#define MINIX_HEADER 32
+
+#define N_MAGIC_OFFSET 1024
+#ifndef __BFD__
+static int GCC_HEADER = sizeof(struct exec);
+#endif
+
+#ifdef __BIG_KERNEL__
+#define SYS_SIZE 0xffff
+#else
+#define SYS_SIZE DEF_SYSSIZE
+#endif
+
+#define DEFAULT_MAJOR_ROOT 0
+#define DEFAULT_MINOR_ROOT 0
+
+/* max nr of sectors of setup: don't change unless you also change
+ * bootsect etc */
+#define SETUP_SECTS 4
+
+#define STRINGIFY(x) #x
+
+typedef union {
+	int i;
+	long l;
+	short s[2];
+	char b[4];
+} conv;
+
+long intel_long(long l)
+{
+	conv t;
+
+	t.b[0] = l & 0xff; l >>= 8;
+	t.b[1] = l & 0xff; l >>= 8;
+	t.b[2] = l & 0xff; l >>= 8;
+	t.b[3] = l & 0xff; l >>= 8;
+	return t.l;
+}
+
+int intel_int(int i)
+{
+	conv t;
+
+	t.b[0] = i & 0xff; i >>= 8;
+        t.b[1] = i & 0xff; i >>= 8;
+        t.b[2] = i & 0xff; i >>= 8;
+        t.b[3] = i & 0xff; i >>= 8;
+        return t.i;
+}
+
+short intel_short(short l)
+{
+	conv t;
+
+	t.b[0] = l & 0xff; l >>= 8;
+	t.b[1] = l & 0xff; l >>= 8;
+	return t.s[0];
+}
+
+void die(const char * str)
+{
+	fprintf(stderr,"%s\n",str);
+	exit(1);
+}
+
+void usage(void)
+{
+	die("Usage: build bootsect setup system [rootdev] [> image]");
+}
+
+int main(int argc, char ** argv)
+{
+	int i,c,id,sz,tmp_int;
+	unsigned long sys_size, tmp_long;
+	char buf[1024];
+#ifndef __BFD__
+	struct exec *ex = (struct exec *)buf;
+#endif
+	char major_root, minor_root;
+	struct stat sb;
+	unsigned char setup_sectors;
+
+	if ((argc < 4) || (argc > 5))
+		usage();
+	if (argc > 4) {
+		if (!strcmp(argv[4], "CURRENT")) {
+			if (stat("/", &sb)) {
+				perror("/");
+				die("Couldn't stat /");
+			}
+			major_root = major(sb.st_dev);
+			minor_root = minor(sb.st_dev);
+		} else if (strcmp(argv[4], "FLOPPY")) {
+			if (stat(argv[4], &sb)) {
+				perror(argv[4]);
+				die("Couldn't stat root device.");
+			}
+			major_root = major(sb.st_rdev);
+			minor_root = minor(sb.st_rdev);
+		} else {
+			major_root = 0;
+			minor_root = 0;
+		}
+	} else {
+		major_root = DEFAULT_MAJOR_ROOT;
+		minor_root = DEFAULT_MINOR_ROOT;
+	}
+	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
+	for (i=0;i<sizeof buf; i++) buf[i]=0;
+	if ((id=open(argv[1],O_RDONLY,0))<0)
+		die("Unable to open 'boot'");
+	if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
+		die("Unable to read header of 'boot'");
+	if (((long *) buf)[0]!=intel_long(0x04100301))
+		die("Non-Minix header of 'boot'");
+	if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
+		die("Non-Minix header of 'boot'");
+	if (((long *) buf)[3] != 0)
+		die("Illegal data segment in 'boot'");
+	if (((long *) buf)[4] != 0)
+		die("Illegal bss in 'boot'");
+	if (((long *) buf)[5] != 0)
+		die("Non-Minix header of 'boot'");
+	if (((long *) buf)[7] != 0)
+		die("Illegal symbol table in 'boot'");
+	i=read(id,buf,sizeof buf);
+	fprintf(stderr,"Boot sector %d bytes.\n",i);
+	if (i != 512)
+		die("Boot block must be exactly 512 bytes");
+	if ((*(unsigned short *)(buf+510)) != (unsigned short)intel_short(0xAA55))
+		die("Boot block hasn't got boot flag (0xAA55)");
+	buf[508] = (char) minor_root;
+	buf[509] = (char) major_root;	
+	i=write(1,buf,512);
+	if (i!=512)
+		die("Write call failed");
+	close (id);
+	
+	if ((id=open(argv[2],O_RDONLY,0))<0)
+		die("Unable to open 'setup'");
+	if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
+		die("Unable to read header of 'setup'");
+	if (((long *) buf)[0]!=intel_long(0x04100301))
+		die("Non-Minix header of 'setup'");
+	if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
+		die("Non-Minix header of 'setup'");
+	if (((long *) buf)[3] != 0)
+		die("Illegal data segment in 'setup'");
+	if (((long *) buf)[4] != 0)
+		die("Illegal bss in 'setup'");
+	if (((long *) buf)[5] != 0)
+		die("Non-Minix header of 'setup'");
+	if (((long *) buf)[7] != 0)
+		die("Illegal symbol table in 'setup'");
+	for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
+#ifdef __BIG_KERNEL__
+	{
+		if (!i) {
+			/* Working with memcpy because of alignment constraints
+			   on Sparc - Gertjan */
+			memcpy(&tmp_long, &buf[2], sizeof(long));
+			if (tmp_long != intel_long(0x53726448) )
+				die("Wrong magic in loader header of 'setup'");
+			memcpy(&tmp_int, &buf[6], sizeof(int));
+			if (tmp_int < intel_int(0x200))
+				die("Wrong version of loader header of 'setup'");
+			buf[0x11] = 1; /* LOADED_HIGH */
+			tmp_long = intel_long(0x100000);
+			memcpy(&buf[0x14], &tmp_long, sizeof(long));  /* code32_start */
+		}
+#endif
+		if (write(1,buf,c)!=c)
+			die("Write call failed");
+#ifdef __BIG_KERNEL__
+	}
+#endif
+	if (c != 0)
+		die("read-error on 'setup'");
+	close (id);
+	setup_sectors = (unsigned char)((i + 511) / 512);
+	/* for compatibility with LILO */
+	if (setup_sectors < SETUP_SECTS)
+		setup_sectors = SETUP_SECTS;
+	fprintf(stderr,"Setup is %d bytes.\n",i);
+	for (c=0 ; c<sizeof(buf) ; c++)
+		buf[c] = '\0';
+	while (i < setup_sectors * 512) {
+		c = setup_sectors * 512 - i;
+		if (c > sizeof(buf))
+			c = sizeof(buf);
+		if (write(1,buf,c) != c)
+			die("Write call failed");
+		i += c;
+	}
+	
+	if ((id=open(argv[3],O_RDONLY,0))<0)
+		die("Unable to open 'system'");
+#ifndef __BFD__
+	if (read(id,buf,GCC_HEADER) != GCC_HEADER)
+		die("Unable to read header of 'system'");
+	if (N_MAGIC(*ex) == ZMAGIC) {
+		GCC_HEADER = N_MAGIC_OFFSET;
+		lseek(id, GCC_HEADER, SEEK_SET);
+	} else if (N_MAGIC(*ex) != QMAGIC)
+		die("Non-GCC header of 'system'");
+	fprintf(stderr,"System is %d kB (%d kB code, %d kB data and %d kB bss)\n",
+		(ex->a_text+ex->a_data+ex->a_bss)/1024,
+		ex->a_text /1024,
+		ex->a_data /1024,
+		ex->a_bss  /1024);
+	sz = N_SYMOFF(*ex) - GCC_HEADER + 4;
+#else
+	if (fstat (id, &sb)) {
+	  perror ("fstat");
+	  die ("Unable to stat 'system'");
+	}
+	sz = sb.st_size;
+	fprintf (stderr, "System is %d kB\n", sz/1024);
+#endif
+	sys_size = (sz + 15) / 16;
+	if (sys_size > SYS_SIZE)
+		die("System is too big");
+	while (sz > 0) {
+		int l, n;
+
+		l = sz;
+		if (l > sizeof(buf))
+			l = sizeof(buf);
+		if ((n=read(id, buf, l)) != l) {
+			if (n == -1) 
+				perror(argv[1]);
+			else
+				fprintf(stderr, "Unexpected EOF\n");
+			die("Can't read 'system'");
+		}
+		if (write(1, buf, l) != l)
+			die("Write failed");
+		sz -= l;
+	}
+	close(id);
+	if (lseek(1, 497, 0) == 497) {
+		if (write(1, &setup_sectors, 1) != 1)
+			die("Write of setup sectors failed");
+	}
+	if (lseek(1,500,0) == 500) {
+		buf[0] = (sys_size & 0xff);
+		buf[1] = ((sys_size >> 8) & 0xff);
+		if (write(1, buf, 2) != 2)
+			die("Write failed");
+	}
+	return(0);
+}
diff -u --recursive --new-file v2.4.3/linux/arch/cris/config.in linux/arch/cris/config.in
--- v2.4.3/linux/arch/cris/config.in	Fri Feb 16 15:53:08 2001
+++ linux/arch/cris/config.in	Tue Apr 17 17:19:24 2001
@@ -5,6 +5,8 @@
 mainmenu_name "Linux/CRIS Kernel Configuration"
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
@@ -36,15 +38,19 @@
 comment 'Hardware setup'
 
 choice 'Processor type' \
-	"Etrax-100-LX	CONFIG_ETRAX100LX	\
-	 Etrax-100-LX-for-xsim-simulator   CONFIG_SVINTO_SIM" Etrax-100-LX
+	"Etrax-100-LX-v1	CONFIG_ETRAX100LX	\
+	 Etrax-100-LX-v2	CONFIG_ETRAX100LX_V2	\
+	 Etrax-100-LX-for-xsim-simulator   CONFIG_SVINTO_SIM" Etrax-100-LX-v1
 
 # For both LX version 1 and the current simulator we enable the low VM mapping
-# Later when LX version 2 and above exist, this should be done with an if
 
-define_bool CONFIG_CRIS_LOW_MAP y
+if [ "$CONFIG_ETRAX100LX" = "y" -o "$CONFIG_SVINTO_SIM" = "y" ]; then
+	define_bool CONFIG_CRIS_LOW_MAP y
+	define_hex  ETRAX_DRAM_VIRTUAL_BASE 60000000
+else
+	define_hex  ETRAX_DRAM_VIRTUAL_BASE c0000000
+fi
 
-hex 'DRAM base (hex)' ETRAX_DRAM_BASE 40000000
 int 'DRAM size (dec, in MB)' ETRAX_DRAM_SIZE 8
 
 int 'Max possible flash size (dec, in MB)' CONFIG_ETRAX_FLASH_LENGTH 2
@@ -69,12 +75,29 @@
 	"Serial-0	CONFIG_DEBUG_PORT0	\
 	 Serial-1	CONFIG_DEBUG_PORT1	\
 	 Serial-2	CONFIG_DEBUG_PORT2	\
-	 Serial-3	CONFIG_DEBUG_PORT3" Serial-0
+	 Serial-3	CONFIG_DEBUG_PORT3	\
+	 disabled	CONFIG_DEBUG_PORT_NULL" Serial-0 
+
+choice 'Product rescue-port' \
+	"Serial-0	CONFIG_RESCUE_SER0	\
+	 Serial-1	CONFIG_RESCUE_SER1	\
+	 Serial-2	CONFIG_RESCUE_SER2	\
+	 Serial-3	CONFIG_RESCUE_SER3" Serial-0
 
 hex 'R_WAITSTATES' DEF_R_WAITSTATES 95a6
 hex 'R_BUS_CONFIG' DEF_R_BUS_CONFIG 104
-hex 'R_DRAM_CONFIG' DEF_R_DRAM_CONFIG 1a200040
-hex 'R_DRAM_TIMING' DEF_R_DRAM_TIMING 5611
+
+bool 'SDRAM support' CONFIG_SDRAM n
+if [ "$CONFIG_SDRAM" = "n" ]; then
+	hex 'R_DRAM_CONFIG' DEF_R_DRAM_CONFIG 1a200040
+	hex 'R_DRAM_TIMING' DEF_R_DRAM_TIMING 5611
+fi
+
+if [ "$CONFIG_SDRAM" = "y" ]; then
+	hex 'R_SDRAM_CONFIG' DEF_R_SDRAM_CONFIG d2fa7878
+	hex 'R_SDRAM_TIMING' DEF_R_SDRAM_TIMING 80004801
+fi
+
 hex 'R_PORT_PA_DIR' DEF_R_PORT_PA_DIR 1c
 hex 'R_PORT_PA_DATA' DEF_R_PORT_PA_DATA 00
 hex 'R_PORT_PB_CONFIG' DEF_R_PORT_PB_CONFIG 00
@@ -82,24 +105,6 @@
 hex 'R_PORT_PB_DATA' DEF_R_PORT_PB_DATA ff
 
 endmenu
-
-# only configure IP numbers if the kernel ifconfig/route setup is enabled
-
-if [ "$CONFIG_KERNEL_IFCONFIG" = "y" ]; then
-  mainmenu_option next_comment	
-  comment 'IP address selection'
-
-  comment 'All addresses are in hexadecimal form without 0x prefix'
-
-  hex 'IP address' ELTEST_IPADR ab1005af
-  hex 'Network' ELTEST_NETWORK ab100000
-  hex 'Netmask' ELTEST_NETMASK ffff0000
-  hex 'Broadcast' ELTEST_BROADCAST ab10ffff
-  hex 'Gateway' ELTEST_GATEWAY ab100101
-  hwaddr 'Ethernet address' ELTEST_ETHADR 00408ccd0000
-
-  endmenu
-fi
 
 # bring in Etrax built-in drivers
 
diff -u --recursive --new-file v2.4.3/linux/arch/cris/cris.ld linux/arch/cris/cris.ld
--- v2.4.3/linux/arch/cris/cris.ld	Tue Feb 13 14:13:43 2001
+++ linux/arch/cris/cris.ld	Fri Apr  6 10:42:55 2001
@@ -1,13 +1,10 @@
 /* ld script to make the Linux/CRIS kernel
  * Authors: Bjorn Wesen (bjornw@axis.com)
- *
- * For now, on Etrax-100 LX, the DRAM starts virtually at 0x6. Normally
- * it should be at 0xc.
  */	
 
 SECTIONS
 {
-	. = 0x60000000;               /* DRAM starts virtually at 0x60000000 */
+	. = @ETRAX_DRAM_VIRTUAL_BASE@;
 	_dram_start = .;
 	_ibr_start = .;
 	. = . + 0x4000; /* see head.S and pages reserved at the start */
@@ -21,6 +18,7 @@
 		*(.fixup)
 		*(.text.__*)
 		*(.rodata)
+		*(.rodata.__*)
 	}
 
 	. = ALIGN(4);                /* Exception table */
@@ -77,5 +75,5 @@
 		*(.exitcall.exit)
         }
 
-	_dram_end = 0x60000000 + @ETRAX_DRAM_SIZE_M@*1024*1024;
+	_dram_end = _dram_start + @ETRAX_DRAM_SIZE_M@*1024*1024;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/cris/defconfig linux/arch/cris/defconfig
--- v2.4.3/linux/arch/cris/defconfig	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/defconfig	Fri Apr  6 10:42:55 2001
@@ -24,10 +24,13 @@
 # Hardware setup
 #
 CONFIG_ETRAX100LX=y
+# CONFIG_ETRAX100LX_V2 is not set
 # CONFIG_SVINTO_SIM is not set
 CONFIG_CRIS_LOW_MAP=y
-ETRAX_DRAM_BASE=40000000
+ETRAX_DRAM_VIRTUAL_BASE=60000000
 ETRAX_DRAM_SIZE=8
+CONFIG_ETRAX_FLASH_LENGTH=2
+CONFIG_ETRAX_FLASH_BUSWIDTH=2
 CONFIG_ETRAX_PA_LEDS=y
 # CONFIG_ETRAX_PB_LEDS is not set
 # CONFIG_ETRAX_90000000_LEDS is not set
@@ -40,8 +43,13 @@
 # CONFIG_DEBUG_PORT1 is not set
 # CONFIG_DEBUG_PORT2 is not set
 # CONFIG_DEBUG_PORT3 is not set
+CONFIG_RESCUE_SER0=y
+# CONFIG_RESCUE_SER1 is not set
+# CONFIG_RESCUE_SER2 is not set
+# CONFIG_RESCUE_SER3 is not set
 DEF_R_WAITSTATES=95a6
 DEF_R_BUS_CONFIG=104
+# CONFIG_SDRAM is not set
 DEF_R_DRAM_CONFIG=1a200040
 DEF_R_DRAM_TIMING=5611
 DEF_R_PORT_PA_DIR=1d
@@ -56,6 +64,87 @@
 CONFIG_ETRAX_ETHERNET=y
 CONFIG_NET_ETHERNET=y
 CONFIG_ETRAX_SERIAL=y
+# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB is not set
+CONFIG_ETRAX_SERIAL_PORT1=y
+# CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB is not set
+# CONFIG_ETRAX_SERIAL_PORT2 is not set
+# CONFIG_ETRAX_SERIAL_PORT3 is not set
+# CONFIG_RS485 is not set
+# CONFIG_ETRAX_SYNCHRONOUS_SERIAL is not set
+# CONFIG_ETRAX_IDE is not set
+CONFIG_ETRAX_AXISFLASHMAP=y
+CONFIG_MTD=y
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_AMDSTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_ETRAX_I2C=y
+CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C=y
+CONFIG_ETRAX_GPIO=y
+CONFIG_ETRAX_PA_BUTTON_BITMASK=02
+CONFIG_PA_CHANGEABLE_DIR=00
+CONFIG_PA_CHANGEABLE_BITS=FF
+CONFIG_PB_CHANGEABLE_DIR=00
+CONFIG_PB_CHANGEABLE_BITS=FF
+# CONFIG_JULIETTE is not set
+# CONFIG_JULIETTE_VIDEO is not set
+# CONFIG_JULIETTE_CCD is not set
+# CONFIG_JULIETTE_SS1M is not set
+# CONFIG_JULIETTE_MEGCCD is not set
+# CONFIG_ETRAX_USB_HOST is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_MTDRAM is not set
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_CFI_GEOMETRY is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_AMDSTD=y
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_SBC_MEDIAGX is not set
+# CONFIG_MTD_ELAN_104NC is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_CSTM_CFI_JEDEC is not set
+# CONFIG_MTD_JEDEC is not set
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_VMAX is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_NAND_SPIA is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
 
 #
 # Block devices
@@ -90,10 +179,6 @@
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
-
-#
-#  
-#
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
@@ -101,6 +186,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -112,11 +198,61 @@
 # CONFIG_NET_SCHED is not set
 
 #
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+# CONFIG_BLK_DEV_IDE is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+
+#
 # SCSI support
 #
 # CONFIG_SCSI is not set
 
 #
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -177,6 +313,16 @@
 # CONFIG_WAN is not set
 
 #
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
 # ISDN subsystem
 #
 # CONFIG_ISDN is not set
@@ -187,6 +333,60 @@
 # CONFIG_CD_NO_IDESCSI is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
 # File systems
 #
 # CONFIG_QUOTA is not set
@@ -259,59 +459,14 @@
 # CONFIG_NLS is not set
 
 #
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-
-#
-# Input core support is needed for joysticks
-#
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
+# Sound
 #
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+# CONFIG_SOUND is not set
 
 #
-# Sound
+# USB support
 #
-# CONFIG_SOUND is not set
+# CONFIG_USB is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/Config.in linux/arch/cris/drivers/Config.in
--- v2.4.3/linux/arch/cris/drivers/Config.in	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/drivers/Config.in	Fri Apr  6 10:42:55 2001
@@ -1,16 +1,74 @@
 mainmenu_option next_comment
 comment 'Drivers for Etrax built-in interfaces'
 
-bool 'Ethernet support' CONFIG_ETRAX_ETHERNET y
+bool 'Ethernet support' CONFIG_ETRAX_ETHERNET
 if [ "$CONFIG_ETRAX_ETHERNET" = "y" ]; then
 # this is just so that the user does not have to go into the
 # normal ethernet driver section just to enable ethernetworking
   define_bool CONFIG_NET_ETHERNET y
+else
+  define_bool CONFIG_NET_ETHERNET n
 fi
 
-bool 'Serial-port support' CONFIG_ETRAX_SERIAL y
+bool 'Serial-port support' CONFIG_ETRAX_SERIAL
+if [ "$CONFIG_ETRAX_SERIAL" = "y" ]; then
+  comment '  Port 0 is always enabled'
+  bool '  Ser0 DTR, RI, DSR, CD on PB' CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB
+  if [ "$CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB" = "y" ]; then
+    int '    Ser0 DTR on PB bit' CONFIG_ETRAX_SER0_DTR_ON_PB_BIT 4
+    int '    Ser0 RI  on PB bit' CONFIG_ETRAX_SER0_RI_ON_PB_BIT 5
+    int '    Ser0 DSR on PB bit' CONFIG_ETRAX_SER0_DSR_ON_PB_BIT 6
+    int '    Ser0 CD  on PB bit' CONFIG_ETRAX_SER0_CD_ON_PB_BIT 7
+  fi
+ 
+  bool '  Serial port 1 enabled' CONFIG_ETRAX_SERIAL_PORT1
+  if [ "$CONFIG_ETRAX_SERIAL_PORT1" = "y" ]; then
+    bool '  Ser1 DTR, RI, DSR, CD on PB' CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB
+    if [ "$CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB" = "y" ]; then
+      int '    Ser1 DTR on PB bit' CONFIG_ETRAX_SER1_DTR_ON_PB_BIT 4
+      int '    Ser1 RI  on PB bit' CONFIG_ETRAX_SER1_RI_ON_PB_BIT 5
+      int '    Ser1 DSR on PB bit' CONFIG_ETRAX_SER1_DSR_ON_PB_BIT 6
+      int '    Ser1 CD  on PB bit' CONFIG_ETRAX_SER1_CD_ON_PB_BIT 7
+    fi
+  fi
+  if [ "$CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB" = "y" -a \
+       "$CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB" = "y" ]; then
+    comment 'Make sure you dont have the same PB bits more than once!'
+  fi
+  bool '  Serial port 2 enabled' CONFIG_ETRAX_SERIAL_PORT2
+  if [ "$CONFIG_ETRAX_SERIAL_PORT2" = "y" ]; then
+    bool '    Ser2 DTR, RI, DSR, CD on PA' CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA
+    if [ "$CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA" = "y" ]; then
+      int '      Ser2 DTR on PA bit' CONFIG_ETRAX_SER2_DTR_ON_PA_BIT 4
+      int '      Ser2 RI  on PA bit' CONFIG_ETRAX_SER2_RI_ON_PA_BIT 5
+      int '      Ser2 DSR on PA bit' CONFIG_ETRAX_SER2_DSR_ON_PA_BIT 6
+      int '      Ser2 CD  on PA bit' CONFIG_ETRAX_SER2_CD_ON_PA_BIT 7
+    fi 
+  fi
+  bool '  Serial port 3 enabled' CONFIG_ETRAX_SERIAL_PORT3
+  bool '  RS-485 support' CONFIG_RS485
+  if [ "$CONFIG_RS485" = "y" ]; then
+    bool '    RS-485 mode on PA' CONFIG_RS485_ON_PA
+    if [ "$CONFIG_RS485_ON_PA" = "y" ]; then
+      int '      RS-485 mode on PA bit' CONFIG_RS485_ON_PA_BIT 3
+    fi
+    bool '    Disable serial receiver' CONFIG_RS485_DISABLE_RECEIVER
+  fi
+fi
+
+bool 'Synchronous serial port support' CONFIG_ETRAX_SYNCHRONOUS_SERIAL
+if [ "$CONFIG_ETRAX_SYNCHRONOUS_SERIAL" = "y" ]; then 
+  bool '  Synchronous serial port 0 enabled' CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0
+  if [ "$CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0" = "y" ]; then
+    bool '    Synchronous serial port 0 uses DMA' CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA y
+  fi
+  bool '  Synchronous serial port 1 enabled' CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1
+  if [ "$CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1" = "y" ]; then
+    bool '    Synchronous serial port 1 uses DMA' CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA y
+  fi 
+fi
 
-bool 'ATA/IDE support' CONFIG_ETRAX_IDE n
+bool 'ATA/IDE support' CONFIG_ETRAX_IDE
 
 if [ "$CONFIG_ETRAX_IDE" = "y" ]; then
 # here we should add the CONFIG_'s necessary to enable the basic
@@ -25,14 +83,18 @@
 
 	define_bool CONFIG_BLK_DEV_IDEDMA y
 	define_bool CONFIG_DMA_NONPCI y
- 
+	
+	int 'Delay for drives to regain consciousness' CONFIG_IDE_DELAY 15
+	
 	choice 'IDE reset pin' \
   	"Port_PB_Bit_7  CONFIG_ETRAX_IDE_PB7_RESET\
    	 Port_G_Bit_27  CONFIG_ETRAX_IDE_G27_RESET\
    	 Port_CSE1_Bit_16  CONFIG_ETRAX_IDE_CSE1_16_RESET" Port_PB_Bit_7 
+else
+	define_bool CONFIG_IDE n
 fi
 
-bool 'Axis flash-map support' CONFIG_ETRAX_AXISFLASHMAP n
+bool 'Axis flash-map support' CONFIG_ETRAX_AXISFLASHMAP
 
 if [ "$CONFIG_ETRAX_AXISFLASHMAP" = "y" ]; then
 # here we define the CONFIG_'s necessary to enable MTD support
@@ -43,7 +105,39 @@
 	define_bool CONFIG_MTD_CFI_INTELEXT n
 	define_bool CONFIG_MTD_CFI_AMDSTD y
 
+	define_bool CONFIG_MTD_AMDSTD y
+
 	define_bool CONFIG_MTD_CHAR y
+	define_bool CONFIG_MTD_BLOCK y
+fi
+
+bool 'I2C support' CONFIG_ETRAX_I2C
+if [ "$CONFIG_ETRAX_I2C" = "y" ]; then
+# this is true for most products since PB-I2C seems to be somewhat
+# flawed.. 
+	bool 'I2C uses PB not PB-I2C' CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
+fi
+
+bool 'GPIO support' CONFIG_ETRAX_GPIO
+if [ "$CONFIG_ETRAX_GPIO" = "y" ]; then
+  hex  '  PA-buttons bitmask' CONFIG_ETRAX_PA_BUTTON_BITMASK 02
+  hex  '  PA user changeable dir mask' CONFIG_PA_CHANGEABLE_DIR 00
+  hex  '  PA user changeable bits mask' CONFIG_PA_CHANGEABLE_BITS FF
+  hex  '  PB user changeable dir mask' CONFIG_PB_CHANGEABLE_DIR 00
+  hex  '  PB user changeable bits mask' CONFIG_PB_CHANGEABLE_BITS FF
+fi
+
+bool 'Juliette support' CONFIG_JULIETTE n
+
+if [ "$CONFIG_JULIETTE" = "y" ]; then
+   source arch/cris/drivers/juliette/Config.in
+fi
+
+bool 'USB host' CONFIG_ETRAX_USB_HOST
+if [ "$CONFIG_ETRAX_USB_HOST" = "y" ]; then
+	define_bool CONFIG_USB y
+	bool '  USB port 1 enabled' CONFIG_ETRAX_USB_HOST_PORT1 n
+	bool '  USB port 2 enabled' CONFIG_ETRAX_USB_HOST_PORT2 n
 fi
 
 endmenu
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/Makefile linux/arch/cris/drivers/Makefile
--- v2.4.3/linux/arch/cris/drivers/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/drivers/Makefile	Fri Apr  6 10:42:55 2001
@@ -6,9 +6,16 @@
 
 obj-y :=
 
-obj-$(CONFIG_ETRAX_ETHERNET)     += ethernet.o
-obj-$(CONFIG_ETRAX_SERIAL)       += serial.o
-obj-$(CONFIG_ETRAX_IDE)          += ide.o
-obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o
+
+obj-$(CONFIG_ETRAX_ETHERNET)           += ethernet.o
+obj-$(CONFIG_ETRAX_SERIAL)             += serial.o
+obj-$(CONFIG_ETRAX_IDE)                += ide.o
+obj-$(CONFIG_ETRAX_AXISFLASHMAP)       += axisflashmap.o
+obj-$(CONFIG_ETRAX_I2C) 	       += i2c.o
+obj-$(CONFIG_ETRAX_GPIO) 	       += gpio.o
+obj-$(CONFIG_ETRAX_USB_HOST)           += usb-host.o
+obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o
+obj-$(CONFIG_JULIETTE)                 += juliette/juliette.o
+subdir-$(CONFIG_JULIETTE)              += juliette
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/axisflashmap.c linux/arch/cris/drivers/axisflashmap.c
--- v2.4.3/linux/arch/cris/drivers/axisflashmap.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/drivers/axisflashmap.c	Fri Apr  6 10:42:55 2001
@@ -11,6 +11,17 @@
  * partition split defined below.
  *
  * $Log: axisflashmap.c,v $
+ * Revision 1.4  2001/02/23 12:47:15  bjornw
+ * Uncached flash in LOW_MAP moved from 0xe to 0x8
+ *
+ * Revision 1.3  2001/02/16 12:11:45  jonashg
+ * MTD driver amd_flash is now included in MTD CVS repository.
+ * (It's now in drivers/mtd).
+ *
+ * Revision 1.2  2001/02/09 11:12:22  jonashg
+ * Support for AMD compatible non-CFI flash chips.
+ * Only tested with Toshiba TC58FVT160 so far.
+ *
  * Revision 1.1  2001/01/12 17:01:18  bjornw
  * * Added axisflashmap.c, a physical mapping for MTD that reads and understands
  *   Axis partition-table format.
@@ -31,7 +42,7 @@
 #include <asm/mmu.h>
 
 #ifdef CONFIG_CRIS_LOW_MAP
-#define FLASH_UNCACHED_ADDR  KSEG_E
+#define FLASH_UNCACHED_ADDR  KSEG_8
 #define FLASH_CACHED_ADDR    KSEG_5
 #else
 #define FLASH_UNCACHED_ADDR  KSEG_E
@@ -205,8 +216,14 @@
 
 	mymtd = do_cfi_probe(&axis_map);
 
+#ifdef CONFIG_MTD_AMDSTD
+	if (!mymtd) {
+		mymtd = do_amd_flash_probe(&axis_map);
+	}
+#endif
+
 	if(!mymtd) {
-		printk("cfi_probe erred %d\n", mymtd);
+		printk("%s: No flash chip found!\n", axis_map.name);
 		return -ENXIO;
 	}
 
@@ -218,7 +235,8 @@
 	 * now at least.
 	 */
 
-	ptable_head = FLASH_CACHED_ADDR + PTABLE_SECTOR + PARTITION_TABLE_OFFSET;
+	ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR +
+		PTABLE_SECTOR + PARTITION_TABLE_OFFSET);
 	pidx++;  /* first partition is always set to the default */
 
 	if ((ptable_head->magic == PARTITION_TABLE_MAGIC)
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/ethernet.c linux/arch/cris/drivers/ethernet.c
--- v2.4.3/linux/arch/cris/drivers/ethernet.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/cris/drivers/ethernet.c	Fri Apr  6 10:42:55 2001
@@ -1,12 +1,23 @@
-/* $Id: ethernet.c,v 1.5 2000/11/29 17:22:22 bjornw Exp $
+/* $Id: ethernet.c,v 1.8 2001/02/27 13:52:48 bjornw Exp $
  *
  * e100net.c: A network driver for the ETRAX 100LX network controller.
  *
- * Copyright (c) 1998-2000 Axis Communications AB.
+ * Copyright (c) 1998-2001 Axis Communications AB.
  *
  * The outline of this driver comes from skeleton.c.
  *
  * $Log: ethernet.c,v $
+ * Revision 1.8  2001/02/27 13:52:48  bjornw
+ * malloc.h -> slab.h
+ *
+ * Revision 1.7  2001/02/23 13:46:38  bjornw
+ * Spellling check
+ *
+ * Revision 1.6  2001/01/26 15:21:04  starvik
+ * Don't disable interrupts while reading MDIO registers (MDIO is slow)
+ * Corrected promiscuous mode
+ * Improved deallocation of IRQs ("ifconfig eth0 down" now works)
+ *
  * Revision 1.5  2000/11/29 17:22:22  bjornw
  * Get rid of the udword types legacy stuff
  *
@@ -39,7 +50,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -53,7 +64,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-#include <asm/svinto.h>
+#include <asm/svinto.h>     /* DMA and register descriptions */
 
 //#define ETHDEBUG
 
@@ -483,9 +494,6 @@
 	unsigned short data;   /* Data read from MDIO */
 	int bitCounter;
 	
-	save_flags(flags);
-	cli();
-	
 	/* Start of frame, OP Code, Physical Address, Register Address */
 	cmd = (MDIO_START << 14) | (MDIO_READ << 12) | (MDIO_PHYS_ADDR << 7) |
 		(reg_num << 2);
@@ -498,8 +506,7 @@
 	for(bitCounter=15; bitCounter>=0 ; bitCounter--) {
 		data |= (e100_receive_mdio_bit() << bitCounter);
 	}
-	
-	restore_flags(flags);
+
 	return data;
 }
 
@@ -555,9 +562,6 @@
 	unsigned short data;
 	int bitCounter;
 
-	save_flags(flags);
-	cli();
-
 	data = e100_get_mdio_reg(MDIO_BASE_CONTROL_REG);
 
 	cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (MDIO_PHYS_ADDR << 7) | (MDIO_BASE_CONTROL_REG << 2);
@@ -569,8 +573,6 @@
 	for(bitCounter = 15; bitCounter >= 0 ; bitCounter--) {
 		e100_send_mdio_bit(GET_BIT(bitCounter, data));
 	}
-	
-	restore_flags(flags);
 }
 
 /* Called by upper layers if they decide it took too long to complete
@@ -858,9 +860,9 @@
 
 	/* Flush the Tx and disable Rx here. */
 
-	free_irq(NETWORK_DMARX_IRQ, NULL);
-	free_irq(NETWORK_DMATX_IRQ, NULL);
-	free_irq(NETWORK_STATUS_IRQ, NULL);
+	free_irq(NETWORK_DMARX_IRQ, (void *)dev);
+	free_irq(NETWORK_DMATX_IRQ, (void *)dev);
+	free_irq(NETWORK_STATUS_IRQ, (void *)dev);
 
 	free_dma(0);
 	free_dma(1);
@@ -926,10 +928,21 @@
 		/* promiscuous mode */
 		lo_bits = 0xfffffffful;
 		hi_bits = 0xfffffffful;
+
+                /* Enable individual receive */
+		*R_NETWORK_REC_CONFIG =
+		  IO_STATE(R_NETWORK_REC_CONFIG, broadcast,  receive) |
+		  IO_STATE(R_NETWORK_REC_CONFIG, ma0,        enable) |
+		  IO_STATE(R_NETWORK_REC_CONFIG, individual, receive);
 	} else if (num_addr == 0) {
 		/* Normal, clear the mc list */
 		lo_bits = 0x00000000ul;
 		hi_bits = 0x00000000ul;
+
+                /* Disable individual receive */
+		*R_NETWORK_REC_CONFIG =
+		  IO_STATE(R_NETWORK_REC_CONFIG, broadcast,  receive) |
+		  IO_STATE(R_NETWORK_REC_CONFIG, ma0,        enable);
 	} else {
 		/* MC mode, receive normal and MC packets */
 		char hash_ix;
@@ -971,6 +984,10 @@
 			}
 			dmi = dmi->next;
 		}
+                /* Disable individual receive */
+		*R_NETWORK_REC_CONFIG =
+		  IO_STATE(R_NETWORK_REC_CONFIG, broadcast,  receive) |
+		  IO_STATE(R_NETWORK_REC_CONFIG, ma0,        enable);
 	}
 	*R_NETWORK_GA_0 = lo_bits;
 	*R_NETWORK_GA_1 = hi_bits;
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/examples/kiobuftest.c linux/arch/cris/drivers/examples/kiobuftest.c
--- v2.4.3/linux/arch/cris/drivers/examples/kiobuftest.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/examples/kiobuftest.c	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,108 @@
+/*
+ * Example showing how to pin down a range of virtual pages from user-space
+ * to be able to do for example DMA directly into them.
+ *
+ * It is necessary because the pages the virtual pointers reference, might
+ * not exist in memory (could be mapped to the zero-page, filemapped etc)
+ * and DMA cannot trigger the MMU to force them in (and would have time 
+ * contraints making it impossible to wait for it anyway).
+ *
+ * Author:  Bjorn Wesen
+ *
+ * $Log: kiobuftest.c,v $
+ * Revision 1.2  2001/02/27 13:52:50  bjornw
+ * malloc.h -> slab.h
+ *
+ * Revision 1.1  2001/01/19 15:57:49  bjornw
+ * Example of how to do direct HW -> user-mode DMA
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/iobuf.h>
+
+#define KIOBUFTEST_MAJOR 124  /* in the local range, experimental */
+
+
+static ssize_t
+kiobuf_read(struct file *filp, char *buf, size_t len, loff_t *ppos)
+{
+
+     struct kiobuf *iobuf;
+     int res, i;
+ 
+     /* Make a kiobuf that maps the entire length the reader has given
+      * us
+      */
+
+     res = alloc_kiovec(1, &iobuf);
+     if (res)
+	     return res;
+     
+     if((res = map_user_kiobuf(READ, iobuf, (unsigned long)buf, len))) {
+	     printk("map_user_kiobuf failed, return %d\n", res);
+	     return res;
+     }
+
+     /* At this point, the virtual area buf[0] -> buf[len-1] will
+      * have corresponding pages mapped in physical memory and locked
+      * until we unmap the kiobuf. They cannot be swapped out or moved
+      * around.
+      */
+
+     printk("nr_pages == %d\noffset == %d\nlength == %d\n",
+	    iobuf->nr_pages, iobuf->offset, iobuf->length);
+
+     for(i = 0; i < iobuf->nr_pages; i++) {
+	     printk("page_add(maplist[%d]) == 0x%x\n", i,
+		    page_address(iobuf->maplist[i]));
+     }
+
+     /* This is the place to create the necessary scatter-gather vector
+      * for the DMA using the iobuf->maplist array and page_address
+      * (don't forget __pa if the DMA needs the actual physical DRAM address)
+      * and run it.
+      */
+
+
+
+
+     /* Release the mapping and exit */
+
+     unmap_kiobuf(iobuf); /* The unlock_kiobuf is implicit here */
+
+     return len;
+}
+
+
+static struct file_operations kiobuf_fops = {
+	owner:    THIS_MODULE,
+	read:     kiobuf_read
+};
+
+static int __init
+kiobuftest_init(void)
+{
+	int res;
+
+	/* register char device */
+
+	res = register_chrdev(KIOBUFTEST_MAJOR, "kiobuftest", &kiobuf_fops);
+	if(res < 0) {
+		printk(KERN_ERR "kiobuftest: couldn't get a major number.\n");
+		return res;
+	}
+
+	printk("Initializing kiobuf-test device\n");
+}
+
+module_init(kiobuftest_init);
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/gpio.c linux/arch/cris/drivers/gpio.c
--- v2.4.3/linux/arch/cris/drivers/gpio.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/gpio.c	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,298 @@
+/* $Id: gpio.c,v 1.4 2001/02/27 13:52:48 bjornw Exp $
+ *
+ * Etrax general port I/O device
+ *
+ * Copyright (c) 1999, 2000, 2001 Axis Communications AB
+ *
+ * Authors:    Bjorn Wesen      (initial version)
+ *             Ola Knutsson     (LED handling)
+ *             Johan Adolfsson  (read/set directions)
+ *
+ * $Log: gpio.c,v $
+ * Revision 1.4  2001/02/27 13:52:48  bjornw
+ * malloc.h -> slab.h
+ *
+ * Revision 1.3  2001/01/24 15:06:48  bjornw
+ * gpio_wq correct type
+ *
+ * Revision 1.2  2001/01/18 16:07:30  bjornw
+ * 2.4 port
+ *
+ * Revision 1.1  2001/01/18 15:55:16  bjornw
+ * Verbatim copy of etraxgpio.c from elinux 2.0 added
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+
+#include <asm/etraxgpio.h>
+#include <asm/svinto.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#define GPIO_MAJOR 120  /* experimental MAJOR number */
+
+#define D(x)
+
+static char gpio_name[] = "etrax gpio";
+
+static wait_queue_head_t *gpio_wq;
+
+static int gpio_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg);
+static int gpio_open(struct inode *inode, struct file *filp);
+static int gpio_release(struct inode *inode, struct file *filp);
+static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
+
+/* private data per open() of this driver */
+
+struct gpio_private {
+	struct gpio_private *next;
+	volatile unsigned char *port, *shadow;
+	volatile unsigned char *dir, *dir_shadow;
+	unsigned char changeable_dir;
+	unsigned char changeable_bits;
+	unsigned char highalarm, lowalarm;
+	wait_queue_head_t alarm_wq;
+	int minor;
+};
+
+/* linked list of alarms to check for */
+
+static struct gpio_private *alarmlist = 0;
+
+#define NUM_PORTS 2
+static volatile unsigned char *ports[2] = { R_PORT_PA_DATA, R_PORT_PB_DATA };
+static volatile unsigned char *shads[2] = {
+	&port_pa_data_shadow, &port_pb_data_shadow };
+
+/* What direction bits that are user changeable 1=changeable*/
+#ifndef CONFIG_PA_CHANGEABLE_DIR
+#define CONFIG_PA_CHANGEABLE_DIR 0x00
+#endif
+#ifndef CONFIG_PB_CHANGEABLE_DIR
+#define CONFIG_PB_CHANGEABLE_DIR 0x00
+#endif
+
+#ifndef CONFIG_PA_CHANGEABLE_BITS
+#define CONFIG_PA_CHANGEABLE_BITS 0xFF
+#endif
+#ifndef CONFIG_PB_CHANGEABLE_BITS
+#define CONFIG_PB_CHANGEABLE_BITS 0xFF
+#endif
+
+
+static unsigned char changeable_dir[2] = { CONFIG_PA_CHANGEABLE_DIR,
+                                           CONFIG_PB_CHANGEABLE_DIR };
+static unsigned char changeable_bits[2] = { CONFIG_PA_CHANGEABLE_BITS,
+                                            CONFIG_PB_CHANGEABLE_BITS };
+
+static volatile unsigned char *dir[2] = { R_PORT_PA_DIR, R_PORT_PB_DIR };
+
+static volatile unsigned char *dir_shadow[2] = {
+	&port_pa_dir_shadow, &port_pb_dir_shadow };
+
+#define LEDS 2
+
+static unsigned int 
+gpio_poll(struct file *filp,
+	  struct poll_table_struct *wait)
+{
+	/* TODO poll on alarms! */
+#if 0
+        if(!ANYTHING_WANTED) {
+		D(printk("gpio_select sleeping task\n"));
+	        select_wait(&gpio_wq, table);
+	        return 0;
+	}
+	D(printk("gpio_select ready\n"));
+#endif
+	return 1;
+}
+
+static int
+gpio_open(struct inode *inode, struct file *filp)
+{
+	struct gpio_private *priv;
+	int p = MINOR(inode->i_rdev);
+
+	if(p >= NUM_PORTS && p != LEDS)
+		return -EINVAL;
+
+	priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private), 
+					      GFP_KERNEL);
+
+	if(!priv)
+		return -ENOMEM;
+
+	priv->minor = p;
+
+	/* initialize the io/alarm struct and link it into our alarmlist */
+
+	priv->next = alarmlist;
+	alarmlist = priv;
+	priv->port = ports[p];
+	priv->shadow = shads[p];
+
+	priv->changeable_dir = changeable_dir[p];
+	priv->changeable_bits = changeable_bits[p];
+	priv->dir = dir[p];
+	priv->dir_shadow = dir_shadow[p];
+
+	priv->highalarm = 0;
+	priv->lowalarm = 0;
+	init_waitqueue_head(&priv->alarm_wq);
+
+	filp->private_data = (void *)priv;
+
+	return 0;
+}
+
+static int
+gpio_release(struct inode *inode, struct file *filp)
+{
+	struct gpio_private *p = alarmlist;
+	struct gpio_private *todel = (struct gpio_private *)filp->private_data;
+
+	/* unlink from alarmlist and free the private structure */
+
+	if(p == todel) {
+		alarmlist = todel->next;
+	} else {
+		while(p->next != todel)
+			p = p->next;
+		p->next = todel->next;
+	}
+
+	kfree(todel);
+
+	return 0;
+}
+
+/* Main device API. ioctl's to read/set/clear bits, as well as to 
+ * set alarms to wait for using a subsequent select().
+ */
+
+static int
+gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
+
+static int
+gpio_ioctl(struct inode *inode, struct file *file,
+	   unsigned int cmd, unsigned long arg)
+{
+	struct gpio_private *priv = (struct gpio_private *)file->private_data;
+
+	if(_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
+		return -EINVAL;
+	}
+
+	switch (_IOC_NR(cmd)) {
+		case IO_READBITS:
+			// read the port
+			return *priv->port;
+		case IO_SETBITS:
+			// set changeable bits with a 1 in arg
+			*priv->port = *priv->shadow |= 
+			  ((unsigned char)arg & priv->changeable_bits);
+			break;
+		case IO_CLRBITS:
+			// clear changeable bits with a 1 in arg
+			*priv->port = *priv->shadow &= 
+			  ~((unsigned char)arg & priv->changeable_bits);
+			break;
+		case IO_HIGHALARM:
+			// set alarm when bits with 1 in arg go high
+			priv->highalarm |= (unsigned char)arg;
+			break;
+		case IO_LOWALARM:
+			// set alarm when bits with 1 in arg go low
+			priv->lowalarm |= (unsigned char)arg;
+			break;
+		case IO_CLRALARM:
+			// clear alarm for bits with 1 in arg
+			priv->highalarm &= ~(unsigned char)arg;
+			priv->lowalarm  &= ~(unsigned char)arg;
+			break;
+		case IO_READDIR:
+			/* Read direction 0=input 1=output */
+			return *priv->dir_shadow;
+		case IO_SETINPUT:
+			/* Set direction 0=unchanged 1=input */
+			*priv->dir = *priv->dir_shadow &= 
+			~((unsigned char)arg & priv->changeable_dir);
+			return *priv->dir_shadow;
+		case IO_SETOUTPUT:
+			/* Set direction 0=unchanged 1=output */
+			*priv->dir = *priv->dir_shadow |= 
+			  ((unsigned char)arg & priv->changeable_dir);
+			return *priv->dir_shadow;
+		default:
+			if(priv->minor == LEDS)
+				return gpio_leds_ioctl(cmd, arg);
+			else
+				return -EINVAL;
+	}
+	
+	return 0;
+}
+
+static int
+gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
+{
+	unsigned char green;
+	unsigned char red;
+
+	switch (_IOC_NR(cmd)) {
+		case IO_LEDACTIVE_SET:
+			green = ((unsigned char) arg) & 1;
+			red   = (((unsigned char) arg) >> 1) & 1;
+			LED_ACTIVE_SET_G(green);
+			LED_ACTIVE_SET_R(red);
+			break;
+		default:
+			return -EINVAL;
+	}
+}
+
+struct file_operations gpio_fops = {
+	owner:       THIS_MODULE,
+	poll:        gpio_poll,
+	ioctl:       gpio_ioctl,
+	open:        gpio_open,
+	release:     gpio_release,
+};
+
+/* main driver initialization routine, called from mem.c */
+
+static __init int
+gpio_init(void)
+{
+	int res;
+
+	/* do the formalities */
+
+	res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
+	if(res < 0) {
+		printk(KERN_ERR "gpio: couldn't get a major number.\n");
+		return res;
+	}
+	
+	printk("ETRAX 100LX GPIO driver v2.1, (c) 2001 Axis Communications AB\n");
+
+	return res;
+}
+
+/* this makes sure that gpio_init is called during kernel boot */
+
+module_init(gpio_init);
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/i2c.c linux/arch/cris/drivers/i2c.c
--- v2.4.3/linux/arch/cris/drivers/i2c.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/i2c.c	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,691 @@
+/*!***************************************************************************
+*!
+*! FILE NAME  : i2c.c
+*!
+*! DESCRIPTION: implements an interface for IIC/I2C, both directly from other
+*!              kernel modules (i2c_writereg/readreg) and from userspace using
+*!              ioctl()'s
+*!
+*! Nov 30 1998  Torbjorn Eliasson  Initial version.
+*!              Bjorn Wesen        Elinux kernel version.
+*! Jan 14 2000  Johan Adolfsson    Fixed PB shadow register stuff - 
+*!                                 don't use PB_I2C if DS1302 uses same bits,
+*!                                 use PB.
+*! $Log: i2c.c,v $
+*! Revision 1.5  2001/02/27 13:52:48  bjornw
+*! malloc.h -> slab.h
+*!
+*! Revision 1.4  2001/02/15 07:17:40  starvik
+*! Corrected usage if port_pb_i2c_shadow
+*!
+*! Revision 1.3  2001/01/26 17:55:13  bjornw
+*! * Made I2C_USES_PB_NOT_PB_I2C a CONFIG option instead of assigning it
+*!   magically. Config.in needs to set it for the options that need it, like
+*!   Dallas 1302 support. Actually, it should be default since it screws up
+*!   the PB bits even if you don't use I2C..
+*! * Include linux/config.h to get the above
+*!
+*! Revision 1.2  2001/01/18 15:49:30  bjornw
+*! 2.4 port of I2C including some cleanups (untested of course)
+*!
+*! Revision 1.1  2001/01/18 15:35:25  bjornw
+*! Verbatim copy of the Etrax i2c driver, 2.0 elinux version
+*!
+*!
+*! ---------------------------------------------------------------------------
+*!
+*! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN
+*!
+*!***************************************************************************/
+/* $Id: i2c.c,v 1.5 2001/02/27 13:52:48 bjornw Exp $ */
+/****************** INCLUDE FILES SECTION ***********************************/
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/config.h>
+
+#include <asm/etraxi2c.h>
+
+#include <asm/system.h>
+#include <asm/svinto.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include "i2c.h"
+
+/****************** I2C DEFINITION SECTION *************************/
+
+#define D(x)
+
+#define I2C_MAJOR 123  /* LOCAL/EXPERIMENTAL */
+static const char i2c_name[] = "i2c";
+
+#define CLOCK_LOW_TIME            8
+#define CLOCK_HIGH_TIME           8
+#define START_CONDITION_HOLD_TIME 8
+#define STOP_CONDITION_HOLD_TIME  8
+#define ENABLE_OUTPUT 0x01
+#define ENABLE_INPUT 0x00
+#define I2C_CLOCK_HIGH 1
+#define I2C_CLOCK_LOW 0
+#define I2C_DATA_HIGH 1
+#define I2C_DATA_LOW 0
+
+#if 0
+/* TODO: fix this so the CONFIG_ETRAX_I2C_USES... is set in Config.in instead */
+#if defined(CONFIG_DS1302) && (CONFIG_DS1302_SDABIT==0) && \
+           (CONFIG_DS1302_SCLBIT == 1)
+#define CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
+#endif
+#endif
+
+#ifdef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
+/* Use PB and not PB_I2C */
+#define SDABIT 0
+#define SCLBIT 1
+#define i2c_enable() 
+#define i2c_disable() 
+
+/* enable or disable output-enable, to select output or input on the i2c bus */
+
+#define i2c_dir_out() \
+  REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, SDABIT, 1)
+#define i2c_dir_in()  \
+  REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, SDABIT, 0)
+
+/* control the i2c clock and data signals */
+
+#define i2c_clk(x) \
+  REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, SCLBIT, x)
+#define i2c_data(x) \
+  REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, SDABIT, x)
+
+/* read a bit from the i2c interface */
+
+#define i2c_getbit() (*R_PORT_PB_READ & (1 << SDABIT))
+
+#else
+/* enable or disable the i2c interface */
+
+#define i2c_enable() *R_PORT_PB_I2C = (port_pb_i2c_shadow |= IO_MASK(R_PORT_PB_I2C, i2c_en))
+#define i2c_disable() *R_PORT_PB_I2C = (port_pb_i2c_shadow &= ~IO_MASK(R_PORT_PB_I2C, i2c_en))
+
+/* enable or disable output-enable, to select output or input on the i2c bus */
+
+#define i2c_dir_out() *R_PORT_PB_I2C = (port_pb_i2c_shadow &= ~IO_MASK(R_PORT_PB_I2C, i2c_oe_))
+#define i2c_dir_in() *R_PORT_PB_I2C = (port_pb_i2c_shadow |= IO_MASK(R_PORT_PB_I2C, i2c_oe_))
+
+/* control the i2c clock and data signals */
+
+#define i2c_clk(x) *R_PORT_PB_I2C = (port_pb_i2c_shadow = (port_pb_i2c_shadow & \
+       ~IO_MASK(R_PORT_PB_I2C, i2c_clk)) | IO_FIELD(R_PORT_PB_I2C, i2c_clk, (x)))
+
+#define i2c_data(x) *R_PORT_PB_I2C = (port_pb_i2c_shadow = (port_pb_i2c_shadow & \
+       ~IO_MASK(R_PORT_PB_I2C, i2c_d)) | IO_FIELD(R_PORT_PB_I2C, i2c_d, (x)))
+
+/* read a bit from the i2c interface */
+
+#define i2c_getbit() (*R_PORT_PB_READ & 0x1)
+#endif
+
+/* use the kernels delay routine */
+
+#define i2c_delay(usecs) udelay(usecs)
+
+
+/****************** FUNCTION DEFINITION SECTION *************************/
+
+
+/* generate i2c start condition */
+
+static void
+i2c_start(void)
+{
+	//
+	// SCL=1 SDA=1
+	//
+	i2c_dir_out();
+	i2c_delay(CLOCK_HIGH_TIME/6);
+	i2c_data(I2C_DATA_HIGH);
+	i2c_clk(I2C_CLOCK_HIGH);
+	i2c_delay(CLOCK_HIGH_TIME);
+	//
+	// SCL=1 SDA=0
+	//
+	i2c_data(I2C_DATA_LOW);
+	i2c_delay(START_CONDITION_HOLD_TIME);
+	//
+	// SCL=0 SDA=0
+	//
+	i2c_clk(I2C_CLOCK_LOW);
+	i2c_delay(CLOCK_LOW_TIME);
+}
+
+/* generate i2c stop condition */
+
+static void
+i2c_stop(void)
+{
+	i2c_dir_out();
+
+	//
+	// SCL=0 SDA=0
+	//
+	i2c_clk(I2C_CLOCK_LOW);
+	i2c_data(I2C_DATA_LOW);
+	i2c_delay(CLOCK_LOW_TIME*2);
+	//
+	// SCL=1 SDA=0
+	//
+	i2c_clk(I2C_CLOCK_HIGH);
+	i2c_delay(CLOCK_HIGH_TIME*2);
+	//
+	// SCL=1 SDA=1
+	//
+	i2c_data(I2C_DATA_HIGH);
+	i2c_delay(STOP_CONDITION_HOLD_TIME);
+
+	i2c_dir_in();
+}
+
+/* write a byte to the i2c interface */
+
+static void
+i2c_outbyte(unsigned char x)
+{
+	int i;
+	
+	i2c_dir_out();
+
+	for (i = 0; i < 8; i++) {
+		if (x & 0x80)
+			i2c_data(I2C_DATA_HIGH);
+		else
+			i2c_data(I2C_DATA_LOW);
+		
+		i2c_delay(CLOCK_LOW_TIME/2);
+		i2c_clk(I2C_CLOCK_HIGH);
+		i2c_delay(CLOCK_HIGH_TIME);
+		i2c_clk(I2C_CLOCK_LOW);
+		i2c_delay(CLOCK_LOW_TIME/2);
+		x <<= 1;
+	}
+	i2c_data(I2C_DATA_LOW);
+	i2c_delay(CLOCK_LOW_TIME/2);
+
+	//
+	// enable input
+	//
+	i2c_dir_in();
+}
+
+/* read a byte from the i2c interface */
+
+static unsigned char
+i2c_inbyte(void)
+{
+	unsigned char aBitByte = 0;
+	int i;
+	int iaa;
+	//int dd= 0;
+
+	//
+	// enable output
+	//
+	i2c_dir_out();
+	//
+	// Release data bus by setting
+	// data high
+	//
+	i2c_data(I2C_DATA_HIGH);
+	//
+	// enable input
+	//
+	i2c_dir_in();
+	//
+	// Use PORT PB instead of I2C
+	// for input. (I2C not working)
+	//
+	i2c_clk(1);
+	i2c_data(1);
+/*	*R_PORT_PB_DATA = *R_PORT_PB_READ | 0x03;*/
+	//
+	// get bits
+	//
+	for (i = 0; i < 8; i++) {
+		i2c_delay(CLOCK_LOW_TIME/2);
+		//
+		// low clock period
+		//
+		i2c_clk(I2C_CLOCK_HIGH);
+		//
+		// switch off I2C
+		//
+		i2c_data(1);
+		i2c_disable();
+		i2c_dir_in();
+		//
+		// wait before getting bit
+		//
+		i2c_delay(CLOCK_HIGH_TIME/2);
+		aBitByte = (aBitByte << 1);
+		iaa = i2c_getbit();
+		aBitByte = aBitByte | iaa ;
+		//if (iaa > 0) dd++;
+		//
+		// wait
+		//
+		i2c_delay(CLOCK_HIGH_TIME/2);
+		//
+		// end clock puls
+		//
+		i2c_enable();
+		i2c_dir_out();
+		i2c_clk(I2C_CLOCK_LOW);
+		//
+		// low clock period
+		//
+		i2c_delay(CLOCK_LOW_TIME/2);
+	}
+	i2c_dir_out();
+	return aBitByte;
+}
+
+/*#---------------------------------------------------------------------------
+*#
+*# FUNCTION NAME: i2c_getack
+*#
+*# DESCRIPTION  : checks if ack was received from ic2
+*#
+*#--------------------------------------------------------------------------*/
+
+static int
+i2c_getack(void)
+{
+	int ack = 1;
+	//
+	// enable output
+	//
+	i2c_dir_out();
+	//
+	// Release data bus by setting
+	// data high
+	//
+	i2c_data(I2C_DATA_HIGH);
+	//
+	// enable input
+	//
+	i2c_dir_in();
+	i2c_delay(CLOCK_HIGH_TIME/4);
+	//
+	// generate ACK clock pulse
+	//
+	i2c_clk(I2C_CLOCK_HIGH);
+	//
+	// Use PORT PB instead of I2C
+	// for input. (I2C not working)
+	//
+	i2c_clk(1);
+	i2c_data(1);
+  
+/*	*R_PORT_PB_DATA = *R_PORT_PB_READ | 0x03;*/
+	//
+	// switch off I2C
+	//
+	i2c_data(1);
+	i2c_disable();
+	i2c_dir_in();
+	//
+	// now wait for ack
+	//
+	i2c_delay(CLOCK_HIGH_TIME/2);
+	//
+	// check for ack
+	//
+	if(i2c_getbit())
+		ack = 0;
+	i2c_delay(CLOCK_HIGH_TIME/2);
+	if(!ack){
+		if(!i2c_getbit()) /* receiver pulld SDA low */
+			ack = 1;
+		i2c_delay(CLOCK_HIGH_TIME/2);
+	}
+
+	//
+	// end clock pulse
+	//
+	i2c_enable();
+	i2c_dir_out();
+	i2c_clk(I2C_CLOCK_LOW);
+	i2c_delay(CLOCK_HIGH_TIME/4);
+	//
+	// enable output
+	//
+	i2c_dir_out();
+	//
+	// remove ACK clock pulse
+	//
+	i2c_data(I2C_DATA_HIGH);
+	i2c_delay(CLOCK_LOW_TIME/2);
+	return ack;
+}
+
+/*#---------------------------------------------------------------------------
+*#
+*# FUNCTION NAME: I2C::sendAck
+*#
+*# DESCRIPTION  : Send ACK on received data
+*#
+*#--------------------------------------------------------------------------*/
+static void
+i2c_sendack(void)
+{
+	//
+	// enable output
+	//
+	i2c_delay(CLOCK_LOW_TIME);
+	i2c_dir_out();
+	//
+	// set ack pulse high
+	//
+	i2c_data(I2C_DATA_LOW);
+	//
+	// generate clock pulse
+	//
+	i2c_delay(CLOCK_HIGH_TIME/6);
+	i2c_clk(I2C_CLOCK_HIGH);
+	i2c_delay(CLOCK_HIGH_TIME);
+	i2c_clk(I2C_CLOCK_LOW);
+	i2c_delay(CLOCK_LOW_TIME/6);
+	//
+	// reset data out
+	//
+	i2c_data(I2C_DATA_HIGH);
+	i2c_delay(CLOCK_LOW_TIME);
+	//
+	i2c_dir_in();
+}
+
+/*#---------------------------------------------------------------------------
+*#
+*# FUNCTION NAME: i2c_writereg
+*#
+*# DESCRIPTION  : Writes a value to an I2C device
+*#
+*#--------------------------------------------------------------------------*/
+int
+i2c_writereg(unsigned char theSlave, unsigned char theReg,
+	     unsigned char theValue)
+{
+	int error, cntr = 3;
+		
+	do {
+		error = 0;
+		//
+		// we don't like to be interrupted
+		//
+		cli();
+		//
+		// generate start condition
+		//
+		i2c_start();
+		//
+		// dummy preamble
+		//
+		i2c_outbyte(0x01);
+		i2c_data(I2C_DATA_HIGH);
+		i2c_clk(I2C_CLOCK_HIGH);
+		i2c_delay(CLOCK_HIGH_TIME); /* Dummy Acknowledge */
+		i2c_clk(I2C_CLOCK_LOW);
+		i2c_delay(CLOCK_LOW_TIME);
+		i2c_clk(I2C_CLOCK_HIGH);
+		i2c_delay(CLOCK_LOW_TIME); /* Repeated Start Condition */
+		i2c_data(I2C_DATA_LOW);
+		i2c_delay(CLOCK_HIGH_TIME);
+		i2c_clk(I2C_CLOCK_LOW);
+		i2c_delay(CLOCK_LOW_TIME);
+
+		i2c_start();
+		//
+		// send slave address
+		//
+		i2c_outbyte(theSlave);
+		//
+		// wait for ack
+		//
+		if(!i2c_getack())
+			error = 1;
+		//
+		// now select register
+		//
+		i2c_dir_out();
+		i2c_outbyte(theReg);
+		//
+		// now it's time to wait for ack
+		//
+		if(!i2c_getack())
+			error |= 2;
+		//
+		// send register register data
+		//
+		i2c_outbyte(theValue);
+		//
+		// now it's time to wait for ack
+		//
+		if(!i2c_getack())
+			error |= 4;
+		//
+		// end byte stream
+		//
+		i2c_stop();
+		//
+		// enable interrupt again
+		//
+		sti();
+		
+	} while(error && cntr--);
+	
+	i2c_delay(CLOCK_LOW_TIME);
+	
+	return -error;
+}
+
+/*#---------------------------------------------------------------------------
+*#
+*# FUNCTION NAME: i2c_readreg
+*#
+*# DESCRIPTION  : Reads a value from the decoder registers.
+*#
+*#--------------------------------------------------------------------------*/
+unsigned char
+i2c_readreg(unsigned char theSlave, unsigned char theReg)
+{
+	unsigned char b = 0;
+	int error, cntr = 3;
+		
+	do {
+		error = 0;
+		//
+		// we don't like to be interrupted
+		//
+		cli();
+		//
+		// generate start condition
+		//
+		i2c_start();
+		//
+		// dummy preamble
+		//
+		i2c_outbyte(0x01);
+		i2c_data(I2C_DATA_HIGH);
+		i2c_clk(I2C_CLOCK_HIGH);
+		i2c_delay(CLOCK_HIGH_TIME); /* Dummy Acknowledge */
+		i2c_clk(I2C_CLOCK_LOW);
+		i2c_delay(CLOCK_LOW_TIME);
+		i2c_clk(I2C_CLOCK_HIGH);
+		i2c_delay(CLOCK_LOW_TIME); /* Repeated Start Condition */
+		i2c_data(I2C_DATA_LOW);
+		i2c_delay(CLOCK_HIGH_TIME);
+		i2c_clk(I2C_CLOCK_LOW);
+		i2c_delay(CLOCK_LOW_TIME);
+    
+		i2c_start();
+    
+		//
+		// send slave address
+		//
+		i2c_outbyte(theSlave);
+		//
+		// wait for ack
+		//
+		if(!i2c_getack())
+			error = 1;
+		//
+		// now select register
+		//
+		i2c_dir_out();
+		i2c_outbyte(theReg);
+		//
+		// now it's time to wait for ack
+		//
+		if(!i2c_getack())
+			error = 1;
+		//
+		// repeat start condition
+		//
+		i2c_delay(CLOCK_LOW_TIME);
+		i2c_start();
+		//
+		// send slave address
+		//
+		i2c_outbyte(theSlave | 0x01);
+		//
+		// wait for ack
+		//
+		if(!i2c_getack())
+			error = 1;
+		//
+		// fetch register
+		//
+		b = i2c_inbyte();
+		//
+		// send Ack
+		//
+		i2c_sendack();
+		//
+		// end sequence
+		//
+		i2c_stop();
+		//
+		// enable interrupt again
+		//
+		sti();	
+	} while(error && cntr--);
+
+	return b;
+}
+
+static int
+i2c_open(struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+static int
+i2c_release(struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+/* Main device API. ioctl's to write or read to/from i2c registers.
+ */
+
+static int
+i2c_ioctl(struct inode *inode, struct file *file,
+	  unsigned int cmd, unsigned long arg)
+{
+	if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) {
+		return -EINVAL;
+	}
+
+	switch (_IOC_NR(cmd)) {
+		case I2C_WRITEREG:
+			// write to an i2c slave
+			D(printk("i2cw %d %d %d\n", 
+				 I2C_ARGSLAVE(arg),
+				 I2C_ARGREG(arg),
+				 I2C_ARGVALUE(arg)));
+
+			return i2c_writereg(I2C_ARGSLAVE(arg),
+					    I2C_ARGREG(arg),
+					    I2C_ARGVALUE(arg));
+		case I2C_READREG:
+		{
+			unsigned char val;
+			// read from an i2c slave
+			D(printk("i2cr %d %d ", 
+				I2C_ARGSLAVE(arg),
+				I2C_ARGREG(arg)));
+			val = i2c_readreg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg));
+			D(printk("= %d\n", val));
+			return val;
+		}					    
+		default:
+			return -EINVAL;
+
+	}
+	
+	return 0;
+}
+
+static struct file_operations i2c_fops = {
+	owner:    THIS_MODULE,
+	ioctl:    i2c_ioctl,
+	open:     i2c_open,
+	release:  i2c_release,
+};
+
+static int __init
+i2c_init(void)
+{
+	int res;
+
+	/* Setup and enable the Port B I2C interface */
+
+#ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
+	*R_PORT_PB_I2C = port_pb_i2c_shadow |= 
+		IO_STATE(R_PORT_PB_I2C, i2c_en,  on) |
+		IO_FIELD(R_PORT_PB_I2C, i2c_d,   1)  |
+		IO_FIELD(R_PORT_PB_I2C, i2c_clk, 1)  |
+		IO_STATE(R_PORT_PB_I2C, i2c_oe_, enable);
+#endif
+
+	port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir0);
+	port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir1);
+
+	*R_PORT_PB_DIR = (port_pb_dir_shadow |=
+			  IO_STATE(R_PORT_PB_DIR, dir0, input)  |
+			  IO_STATE(R_PORT_PB_DIR, dir1, output));
+
+	/* register char device */
+
+	res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops);
+	if(res < 0) {
+		printk(KERN_ERR "i2c: couldn't get a major number.\n");
+		return res;
+	}
+
+	printk("I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n");
+}
+
+/* this makes sure that i2c_init is called during boot */
+
+module_init(i2c_init);
+
+/****************** END OF FILE i2c.c ********************************/
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/i2c.h linux/arch/cris/drivers/i2c.h
--- v2.4.3/linux/arch/cris/drivers/i2c.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/i2c.h	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,16 @@
+/* $Id: i2c.h,v 1.2 2001/01/18 15:49:30 bjornw Exp $ */
+
+/* High level I2C actions */
+int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue);
+unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg);
+
+/* Low level I2C */
+static void i2c_start(void);
+static void i2c_stop(void);
+static void i2c_outbyte(unsigned char x);
+static unsigned char i2c_inbyte(void);
+static int i2c_getack(void);
+static void i2c_sendack(void);
+
+
+
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/ide.c linux/arch/cris/drivers/ide.c
--- v2.4.3/linux/arch/cris/drivers/ide.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/cris/drivers/ide.c	Fri Apr  6 10:42:55 2001
@@ -1,4 +1,4 @@
-/* $Id: ide.c,v 1.4 2001/01/10 21:14:32 bjornw Exp $
+/* $Id: ide.c,v 1.9 2001/03/01 13:11:18 bjornw 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,23 @@
  *             Mikael Starvik     (pio setup stuff)
  *
  * $Log: ide.c,v $
+ * Revision 1.9  2001/03/01 13:11:18  bjornw
+ * 100 -> HZ
+ *
+ * Revision 1.8  2001/03/01 09:32:56  matsfg
+ * Moved IDE delay to a CONFIG-parameter instead
+ *
+ * Revision 1.7  2001/02/23 13:46:38  bjornw
+ * Spellling check
+ *
+ * Revision 1.6  2001/02/22 15:44:30  bjornw
+ * * Use ioremap when mapping the CSE1 memory-mapped reset-line for LX v2
+ * * sw_len for a 65536 descriptor is 0, not 65536
+ * * Express concern for G27 reset code
+ *
+ * Revision 1.5  2001/02/16 07:35:38  matsfg
+ * Now handles DMA request blocks between 64k and 128k by split into two descriptors.
+ *
  * Revision 1.4  2001/01/10 21:14:32  bjornw
  * Initialize hwif->ideproc, for the new way of handling ide_xxx_data
  *
@@ -63,8 +80,13 @@
 /* number of Etrax DMA descriptors */
 #define MAX_DMA_DESCRS 64
 
+#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
+/* address where the memory-mapped IDE reset bit lives, if used */
+static volatile unsigned long *reset_addr;
+#endif
+
 #define LOWDB(x)
-#define D(x)
+#define D(x) 
 
 void OUT_BYTE(unsigned char data, ide_ioreg_t reg) {
 	LOWDB(printk("ob: data 0x%x, reg 0x%x\n", data, reg));
@@ -208,7 +230,8 @@
 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)
+void __init 
+init_e100_ide (void)
 {
 	volatile unsigned int dummy;
 	int h;
@@ -226,6 +249,8 @@
 	}
 	/* actually reset and configure the etrax100 ide/ata interface */
 
+	/* This is mystifying; why is not G27 SET anywhere ? It's just reset here twice. */
+
 	/* de-assert bus-reset */
 #ifdef CONFIG_ETRAX_IDE_PB7_RESET  
 	port_pb_dir_shadow = port_pb_dir_shadow | 
@@ -252,7 +277,16 @@
 	*R_GEN_CONFIG = genconfig_shadow;
 
 #ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
-	*(volatile long *)(MEM_CSE1_START | MEM_NON_CACHEABLE) = 0;
+#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;
+#endif
 #endif
 
 	/* wait some */
@@ -262,9 +296,11 @@
 	dummy = 3;
 
 #ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
-	*(volatile long *)(MEM_CSE1_START | MEM_NON_CACHEABLE) = 1 << 16;
-	*R_PORT_G_DATA = 0;  /* de-assert bus-reset */
+	*reset_addr = 1 << 16;
 #endif
+#ifdef CONFIG_ETRAX_IDE_G27_RESET
+	*R_PORT_G_DATA = 0; /* de-assert bus-reset */
+#endif 
 
 	/* make a dummy read to set the ata controller in a proper state */
 	dummy = *R_ATA_STATUS_DATA;
@@ -286,9 +322,9 @@
 			     IO_STATE( R_IRQ_MASK0_SET, ata_irq2, set ) |
 			     IO_STATE( R_IRQ_MASK0_SET, ata_irq3, set ) );
 
-	printk("ide: waiting 10 seconds for drives to regain consciousness\n");
+	printk("ide: waiting %d seconds for drives to regain consciousness\n", CONFIG_IDE_DELAY);
 
-	h = jiffies + 1000;
+	h = jiffies + (CONFIG_IDE_DELAY * HZ);
 	while(jiffies < h) ;
 
   /* reset the dma channels we will use */
@@ -560,14 +596,6 @@
 			return 1;
 		}
 
-		/* uh.. I'm lazy.. if size >= 65536, it should loop below and split it in
-		   more than one descriptor */
-
-		if(size >= 65536) {
-			printk("too large ATA DMA request block, size = %d!\n", size);
-			return 1;
-		}
-
 		/* however, this case is more difficult - R_ATA_TRANSFER_CNT cannot be more
 		   than 65536 words per transfer, so in that case we need to either 
 		   1) use a DMA interrupt to re-trigger R_ATA_TRANSFER_CNT and continue with
@@ -581,8 +609,22 @@
 			return 1;
 		}
 
-		/* ok we want to do IO at addr, size bytes. set up a new descriptor entry */
+		/* If size > 65536 it has to be splitted into new descriptors. Since we don't handle 
+                   size > 131072 only one split is necessary */
 
+		if(size > 65536) {
+ 		        /* ok we want to do IO at addr, size bytes. set up a new descriptor entry */
+                        ata_descrs[count].sw_len = 0;  /* 0 means 65536, this is a 16-bit field */
+                        ata_descrs[count].ctrl = 0;
+                        ata_descrs[count].buf = addr;
+                        ata_descrs[count].next = virt_to_phys(&ata_descrs[count + 1]);
+                        count++;
+                        ata_tot_size += 65536;
+                        /* size and addr should refere to not handled data */
+                        size -= 65536;
+                        addr += 65536;
+                }
+		/* ok we want to do IO at addr, size bytes. set up a new descriptor entry */
 		ata_descrs[count].sw_len = size;
 		ata_descrs[count].ctrl = 0;
 		ata_descrs[count].buf = addr;
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/serial.c linux/arch/cris/drivers/serial.c
--- v2.4.3/linux/arch/cris/drivers/serial.c	Fri Mar  2 18:38:40 2001
+++ linux/arch/cris/drivers/serial.c	Fri Apr  6 10:42:55 2001
@@ -1,12 +1,26 @@
-/* $Id: serial.c,v 1.6 2000/11/22 16:36:09 bjornw Exp $
+/* $Id: serial.c,v 1.10 2001/03/05 13:14:07 bjornw Exp $
  *
  * Serial port driver for the ETRAX 100LX chip
  *
- *      Copyright (C) 1998, 1999, 2000  Axis Communications AB
+ *      Copyright (C) 1998, 1999, 2000, 2001  Axis Communications AB
  *
  *      Many, many authors. Based once upon a time on serial.c for 16x50.
  *
  * $Log: serial.c,v $
+ * Revision 1.10  2001/03/05 13:14:07  bjornw
+ * Another spelling fix
+ *
+ * Revision 1.9  2001/02/23 13:46:38  bjornw
+ * Spellling check
+ *
+ * Revision 1.8  2001/01/23 14:56:35  markusl
+ * Made use of ser1 optional
+ * Needed by USB
+ *
+ * Revision 1.7  2001/01/19 16:14:48  perf
+ * Added kernel options for serial ports 234.
+ * Changed option names from CONFIG_ETRAX100_XYZ to CONFIG_ETRAX_XYZ.
+ *
  * Revision 1.6  2000/11/22 16:36:09  bjornw
  * Please marketing by using the correct case when spelling Etrax.
  *
@@ -176,7 +190,7 @@
  *
  */
 
-static char *serial_version = "$Revision: 1.6 $";
+static char *serial_version = "$Revision: 1.10 $";
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -252,12 +266,12 @@
 //#define SERIAL_HANDLE_EARLY_ERRORS
 
 
-#ifndef CONFIG_ETRAX100_SERIAL_RX_TIMEOUT_TICKS
+#ifndef CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS
 /* Default number of timer ticks before flushing rx fifo 
  * When using "little data, low latency applications: use 0
  * When using "much data applications (PPP)" use ~5
  */
-#define CONFIG_ETRAX100_SERIAL_RX_TIMEOUT_TICKS 5 
+#define CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS 5 
 #endif
 
 #define MAX_FLUSH_TIME 8
@@ -367,36 +381,36 @@
 {
 /* Ser 0 */
   {
-#if defined(CONFIG_ETRAX100_SER0_DTR_RI_DSR_CD_ON_PB)
+#if defined(CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB)
     R_PORT_PB_DATA,  &port_pb_data_shadow,  &port_pb_dir_shadow,
-    CONFIG_ETRAX100_SER0_DTR_ON_PB_BIT,
-	  CONFIG_ETRAX100_SER0_RI_ON_PB_BIT, 
-	  CONFIG_ETRAX100_SER0_DSR_ON_PB_BIT, 
-	  CONFIG_ETRAX100_SER0_CD_ON_PB_BIT
+    CONFIG_ETRAX_SER0_DTR_ON_PB_BIT,
+    CONFIG_ETRAX_SER0_RI_ON_PB_BIT, 
+    CONFIG_ETRAX_SER0_DSR_ON_PB_BIT, 
+    CONFIG_ETRAX_SER0_CD_ON_PB_BIT
 #else
     &dummy_ser0, &dummy_ser0, &dummy_dir_ser0, 0, 1, 2, 3
 #endif   
   },
 /* Ser 1 */
   {
-#if defined(CONFIG_ETRAX100_SER1_DTR_RI_DSR_CD_ON_PB)
+#if defined(CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB)
     R_PORT_PB_DATA,  &port_pb_data_shadow,  &port_pb_dir_shadow,
-    CONFIG_ETRAX100_SER1_DTR_ON_PB_BIT,
-	  CONFIG_ETRAX100_SER1_RI_ON_PB_BIT, 
-	  CONFIG_ETRAX100_SER1_DSR_ON_PB_BIT, 
-	  CONFIG_ETRAX100_SER1_CD_ON_PB_BIT
+    CONFIG_ETRAX_SER1_DTR_ON_PB_BIT,
+    CONFIG_ETRAX_SER1_RI_ON_PB_BIT, 
+    CONFIG_ETRAX_SER1_DSR_ON_PB_BIT, 
+    CONFIG_ETRAX_SER1_CD_ON_PB_BIT
 #else
     &dummy_ser1, &dummy_ser1, &dummy_dir_ser1, 0, 1, 2, 3
 #endif   
   },  
 /* Ser 2 */
   {
-#if defined(CONFIG_ETRAX100_SER2_DTR_RI_DSR_CD_ON_PA)
+#if defined(CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA)
     R_PORT_PA_DATA,  &port_pa_data_shadow,  &port_pa_dir_shadow,
-    CONFIG_ETRAX100_SER2_DTR_ON_PA_BIT,
-	  CONFIG_ETRAX100_SER2_RI_ON_PA_BIT, 
-	  CONFIG_ETRAX100_SER2_DSR_ON_PA_BIT, 
-	  CONFIG_ETRAX100_SER2_CD_ON_PA_BIT
+    CONFIG_ETRAX_SER2_DTR_ON_PA_BIT,
+    CONFIG_ETRAX_SER2_RI_ON_PA_BIT, 
+    CONFIG_ETRAX_SER2_DSR_ON_PA_BIT, 
+    CONFIG_ETRAX_SER2_CD_ON_PA_BIT
 #else
     &dummy_ser2, &dummy_ser2, &dummy_dir_ser2, 0, 1, 2, 3
 #endif   
@@ -459,7 +473,7 @@
 static struct semaphore tmp_buf_sem = MUTEX;
 #endif
 
-#ifdef CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST
+#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
 #define TIMER1_IRQ_NBR 3
 
 /* clock select 10 for timer 1 gives 230400 Hz */
@@ -494,7 +508,7 @@
 	*R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set);
 	fast_timer_started = 1;
 }
-#endif /* CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST */
+#endif /* CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST */
 
 /*
  * This function maps from the Bxxxx defines in asm/termbits.h into real
@@ -1267,12 +1281,12 @@
 
 /* dma fifo/buffer timeout handler
    forces an end-of-packet for the dma input channel if no chars 
-   have been received for CONFIG_ETRAX100_RX_TIMEOUT_TICKS/100 s.
-   If CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST is configured then this
+   have been received for CONFIG_ETRAX_RX_TIMEOUT_TICKS/100 s.
+   If CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is configured then this
    handler is instead run at 15360 Hz.
 */
 
-#ifndef CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST
+#ifndef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
 static int timeout_divider = 0;
 #endif
 
@@ -1467,7 +1481,7 @@
 		info->xmit.buf = (unsigned char *) page;
 		
 #ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttyS%d (xmit_buf 0x%x)...\n", info->line, info->xmit_buf);
+	printk("starting up ttyS%d (xmit_buf 0x%x)...\n", info->line, info->xmit.buf);
 #endif
 
 	if(info->tty) {
@@ -2688,12 +2702,15 @@
 		return -ENODEV;
 
 	/* dont allow opening ports that are not enabled in the HW config */
-
-#ifndef CONFIG_ETRAX100_SERIAL_PORT2
+#ifndef CONFIG_ETRAX_SERIAL_PORT1
+	if (line == 1)
+		return -ENODEV;
+#endif
+#ifndef CONFIG_ETRAX_SERIAL_PORT2
 	if (line == 2)
 		return -ENODEV;
 #endif
-#ifndef CONFIG_ETRAX100_SERIAL_PORT3
+#ifndef CONFIG_ETRAX_SERIAL_PORT3
 	if (line == 3)
 		return -ENODEV;
 #endif
@@ -2955,7 +2972,7 @@
 	for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
 		info->line = i;
 		info->tty = 0;
-		info->type = PORT_ETRAX100;
+		info->type = PORT_ETRAX;
 		info->tr_running = 0;
 		info->fifo_magic = 0;
 		info->fifo_didmagic = 0;
@@ -2990,25 +3007,27 @@
 	if(request_irq(8, ser_interrupt, SA_INTERRUPT, "serial ", NULL))
 		panic("irq8");
 #endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT1
 	if(request_irq(24, tr_interrupt, SA_INTERRUPT, "serial 1 dma tr", NULL))
 		panic("irq24");
 	if(request_irq(25, rec_interrupt, SA_INTERRUPT, "serial 1 dma rec", NULL))
 		panic("irq25");
-#ifdef CONFIG_ETRAX100_SERIAL_PORT2
+#endif
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
 	/* DMA Shared with par0 (and SCSI0 and ATA) */
 	if(request_irq(18, tr_interrupt, SA_SHIRQ, "serial 2 dma tr", NULL))
 		panic("irq18");
 	if(request_irq(19, rec_interrupt, SA_SHIRQ, "serial 2 dma rec", NULL))
 		panic("irq19");
 #endif
-#ifdef CONFIG_ETRAX100_SERIAL_PORT3
+#ifdef CONFIG_ETRAX_SERIAL_PORT3
 	/* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */
 	if(request_irq(20, tr_interrupt, SA_SHIRQ, "serial 3 dma tr", NULL))
 		panic("irq20");
 	if(request_irq(21, rec_interrupt, SA_SHIRQ, "serial 3 dma rec", NULL))
 		panic("irq21");
 #endif
-#ifdef CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST
+#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
 	/* TODO: a timeout_interrupt needs to be written that calls timeout_handler */
 	if(request_irq(TIMER1_IRQ_NBR, timeout_interrupt, SA_SHIRQ,
 		       "fast serial dma timeout", NULL)) {
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/serial.h linux/arch/cris/drivers/serial.h
--- v2.4.3/linux/arch/cris/drivers/serial.h	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/drivers/serial.h	Fri Apr  6 10:42:55 2001
@@ -4,8 +4,8 @@
  * Copyright (C) 1998, 1999, 2000 Axis Communications AB
  */
 
-#ifndef _ETRAX100_SERIAL_H
-#define _ETRAX100_SERIAL_H
+#ifndef _ETRAX_SERIAL_H
+#define _ETRAX_SERIAL_H
 
 #include <linux/config.h>
 #include <linux/circ_buf.h>
@@ -64,7 +64,7 @@
 	unsigned long		event;
 	unsigned long		last_active;
 	int			line;
-	int                     type;  /* PORT_ETRAX100 */
+	int                     type;  /* PORT_ETRAX */
 	int			count;	    /* # of fd on device */
 	int			blocked_open; /* # of blocked opens */
 	long			session; /* Session of opening process */
@@ -93,7 +93,7 @@
  * system.
  */
 
-#define PORT_ETRAX100 1
+#define PORT_ETRAX 1
 
 /*
  * Events are used to schedule things to happen at timer-interrupt
@@ -103,4 +103,4 @@
 
 #endif /* __KERNEL__ */
 
-#endif /* !(_ETRAX100_SERIAL_H) */
+#endif /* !(_ETRAX_SERIAL_H) */
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/sync_serial.c linux/arch/cris/drivers/sync_serial.c
--- v2.4.3/linux/arch/cris/drivers/sync_serial.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/sync_serial.c	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,873 @@
+/*  
+ * Simple synchronous serial port driver for ETRAX 100LX.
+ *
+ * Synchronous serial ports are used for continous streamed data like audio.
+ * The deault setting for this driver is compatible with the STA 013 MP3 decoder
+ * The driver can easily be tuned to fit other audio encoder/decoders and SPI
+ *
+ * Copyright (c) 2001 Axis Communications AB
+ * 
+ * Author: Mikael Starvik 
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/svinto.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/sync_serial.h>
+
+/* The receiver is a bit tricky beacuse of the continous stream of data. */
+/*									 */
+/* Two DMA descriptors are linked together. Each DMA descriptor is	 */
+/* responsible for one half of a common buffer.				 */
+/*									 */
+/* ------------------------------					 */
+/* |   ----------   ----------	|					 */
+/* --> | Descr1 |-->| Descr2 |---					 */
+/*     ----------   ----------						 */
+/*	 |	       |						 */
+/*	 v	       v						 */
+/*	 -----------------------------					 */
+/*	 |	      BUFFER	     |					 */
+/*	 -----------------------------					 */
+/*	 |		|						 */
+/*	readp	      writep						 */
+/*									 */
+/* If the application keeps up the pace readp will be right after writep.*/
+/* If the application can't keep the pace we have to throw away data.	 */ 
+/* The idea is that readp should be ready with the data pointed out by	 */
+/* Descr1 when the DMA has filled in Descr2. Otherwise we will discard	 */
+/* the rest of the data pointed out by Descr1 and set readp to the start */
+/* of Descr2								 */
+
+#define SYNC_SERIAL_MAJOR 125
+
+#define IN_BUFFER_SIZE 8192
+#define OUT_BUFFER_SIZE 4096
+
+#define DEBUG(x) 
+
+/* Define some macros to access Etrax 100 registers */
+#define SETF(var, reg, field, val) var = (var & ~IO_MASK(##reg##, field)) | \
+					  IO_FIELD(##reg##, field, val)
+#define SETS(var, reg, field, val) var = (var & ~IO_MASK(##reg##, field)) | \
+					  IO_STATE(##reg##, field, val)
+
+typedef struct sync_port
+{
+	/* Etrax registers and bits*/
+	volatile unsigned * const status;
+	volatile unsigned * const ctrl_data;
+	volatile unsigned * const output_dma_first;
+	volatile unsigned char * const output_dma_cmd;
+	volatile unsigned char * const output_dma_clr_irq;
+	volatile unsigned * const input_dma_first;
+	volatile unsigned char * const input_dma_cmd;
+	volatile unsigned char * const input_dma_clr_irq;
+	volatile unsigned * const data_out;
+	volatile unsigned * const data_in;
+	char data_avail_bit; /* In R_IRQ_MASK1_RD */
+	char transmitter_ready_bit; /* In R_IRQ_MASK1_RD */
+	char ready_irq_bit; /* In R_IRQ_MASK1_SET and R_IRQ_MASK1_CLR */
+	char input_dma_eop_bit;   /* In R_IRQ_MASK2_RD */
+	char input_dma_descr_bit; /* In R_IRQ_MASK2_RD */
+	char output_dma_bit; /* In R_IRQ_MASK2_RD */
+	char eop_bit; /* In R_SET_EOP */
+
+	int enabled;  /* 1 if port is enabled */
+	int use_dma;  /* 1 if port uses dma */
+	int port_nbr; /* Port 0 or 1 */
+	unsigned ctrl_data_shadow; /* Register shadow */
+	char busy; /* 1 if port is busy */
+	wait_queue_head_t out_wait_q;
+	wait_queue_head_t in_wait_q;
+	struct etrax_dma_descr out_descr;
+	struct etrax_dma_descr in_descr1;
+	struct etrax_dma_descr in_descr2;
+	char out_buffer[OUT_BUFFER_SIZE];
+	int out_count; /* Remaining bytes for current transfer */
+	char* outp; /* Current position in out_buffer */
+	char in_buffer[IN_BUFFER_SIZE];
+	volatile char* readp;  /* Next byte to be read by application */
+	volatile char* writep; /* Next byte to be written by etrax */
+	int odd_output; /* 1 if writing odd nible in 12 bit mode */
+	int odd_input;  /* 1 if reading odd nible in 12 bit mode */
+} sync_port;
+
+
+static int etrax_sync_serial_init(void);
+static void initialize_port(int portnbr);
+static int sync_serial_open(struct inode *, struct file*);
+static int sync_serial_release(struct inode*, struct file*);
+static int sync_serial_ioctl(struct inode*, struct file*,
+			     unsigned int cmd, unsigned long arg);
+static ssize_t sync_serial_write(struct file * file, const char * buf, 
+				 size_t count, loff_t *ppos);
+static ssize_t sync_serial_manual_write(struct file * file, const char * buf, 
+					size_t count, loff_t *ppos);
+static ssize_t sync_serial_read(struct file *file, char *buf, 
+				size_t count, loff_t *ppos);
+static void send_word(sync_port* port);
+static void start_dma(struct sync_port *port, const char* data, int count);
+static void start_dma_in(sync_port* port);
+static void tr_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static void manual_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static void flush_handler(void);
+
+/* The ports */
+static struct sync_port ports[]=
+{
+	{
+		R_SYNC_SERIAL1_STATUS,  /* status */
+		R_SYNC_SERIAL1_CTRL,    /* ctrl_data */
+		R_DMA_CH8_FIRST,	    /* output_dma_first */
+		R_DMA_CH8_CMD,	    /* output_dma_cmd */
+		R_DMA_CH8_CLR_INTR,	    /* output_dma_clr_irq */
+		R_DMA_CH9_FIRST,	    /* input_dma_first */
+		R_DMA_CH9_CMD,	    /* input_dma_cmd */
+		R_DMA_CH9_CLR_INTR,	    /* input_dma_clr_irq */
+		R_SYNC_SERIAL1_TR_DATA, /* data_out */
+		R_SYNC_SERIAL1_REC_DATA,/* data in */
+		IO_BITNR(R_IRQ_MASK1_RD, ser1_data),   /* data_avail_bit */
+		IO_BITNR(R_IRQ_MASK1_RD, ser1_ready),  /* transmitter_ready_bit */
+		IO_BITNR(R_IRQ_MASK1_SET, ser1_ready), /* ready_irq_bit */
+		IO_BITNR(R_IRQ_MASK2_RD, dma9_eop),	   /* input_dma_eop_bit */
+		IO_BITNR(R_IRQ_MASK2_RD, dma9_descr),  /* input_dma_descr_bit */
+		IO_BITNR(R_IRQ_MASK2_RD, dma8_eop),	   /* output_dma_bit */
+		IO_BITNR(R_SET_EOP, ch9_eop)	   /* eop_bit */
+	},
+	{
+		R_SYNC_SERIAL3_STATUS,  /* status */
+		R_SYNC_SERIAL3_CTRL,    /* ctrl_data */
+		R_DMA_CH4_FIRST,	    /* output_dma_first */
+		R_DMA_CH4_CMD,	    /* output_dma_cmd */
+		R_DMA_CH4_CLR_INTR,	    /* output_dma_clr_irq */
+		R_DMA_CH5_FIRST,	    /* input_dma_first */
+		R_DMA_CH5_CMD,	    /* input_dma_cmd */
+		R_DMA_CH5_CLR_INTR,	    /* input_dma_clr_irq */
+		R_SYNC_SERIAL3_TR_DATA, /* data_out */
+		R_SYNC_SERIAL3_REC_DATA,/* data in */
+		IO_BITNR(R_IRQ_MASK1_RD, ser3_data),   /* data_avail_bit */
+		IO_BITNR(R_IRQ_MASK1_RD, ser3_ready),  /* transmitter_ready_bit */
+		IO_BITNR(R_IRQ_MASK1_SET, ser3_ready), /* ready_irq_bit */
+		IO_BITNR(R_IRQ_MASK2_RD, dma5_eop),	   /* input_dma_eop_bit */
+		IO_BITNR(R_IRQ_MASK2_RD, dma5_descr),  /* input_dma_eop_bit */
+		IO_BITNR(R_IRQ_MASK2_RD, dma4_eop),	   /* output_dma_bit */
+		IO_BITNR(R_SET_EOP, ch5_eop)	   /* eop_bit */
+	}
+};
+
+/* Register shadows */
+static unsigned sync_serial_prescale_shadow = 0;
+static unsigned gen_config_ii_shadow = 0;
+
+/* Timer used to flush data from the DMA */
+static struct timer_list flush_timer;
+
+#define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
+
+static struct file_operations sync_serial_fops = {
+       owner:	THIS_MODULE,
+       write:	sync_serial_write,
+       read:	sync_serial_read,
+       ioctl:	sync_serial_ioctl,
+       open:	sync_serial_open,
+       release: sync_serial_release
+};
+
+static int __init etrax_sync_serial_init(void)
+{
+	ports[0].enabled = 0;
+	ports[1].enabled = 0;
+
+	if (register_chrdev(SYNC_SERIAL_MAJOR,"sync serial", &sync_serial_fops) <0 ) 
+	{
+		printk("unable to get major for synchronous serial port\n");
+		return -EBUSY;
+	}
+
+	/* Deselect synchronous serial ports */
+	SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
+	SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
+	SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, ser3, select);
+	*R_GEN_CONFIG_II = gen_config_ii_shadow;
+  
+	/* Initialize Ports */
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0)
+	ports[0].enabled = 1;
+	SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser1, ss1extra); 
+	SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)
+	ports[0].use_dma = 1;
+	initialize_port(0);
+	if(request_irq(24, tr_interrupt, 0, "synchronous serial 1 dma tr", NULL))
+		 panic("Can't allocate sync serial port 1 IRQ");
+	if(request_irq(25, rx_interrupt, 0, "synchronous serial 1 dma rx", NULL))
+		panic("Can't allocate sync serial port 1 IRQ");
+	RESET_DMA(8); WAIT_DMA(8);
+	RESET_DMA(9); WAIT_DMA(9);
+	*R_DMA_CH8_CLR_INTR = 3;  /* Clear IRQ */
+	*R_DMA_CH9_CLR_INTR = 3;  /* Clear IRQ */
+	*R_IRQ_MASK2_SET =
+	  IO_STATE(R_IRQ_MASK2_SET, dma8_eop, set) |
+	  IO_STATE(R_IRQ_MASK2_SET, dma8_descr, set) |
+          IO_STATE(R_IRQ_MASK2_SET, dma9_eop, set) | 
+          IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set);
+	start_dma_in(&ports[0]);
+#else
+	ports[0].use_dma = 0;
+	initialize_port(0);
+	if (request_irq(8, manual_interrupt, SA_SHIRQ, "synchronous serial manual irq", NULL))
+		panic("Can't allocate sync serial manual irq");
+	*R_IRQ_MASK1_SET = IO_STATE(R_IRQ_MASK1_SET, ser1_data, set);	 
+#endif
+#endif
+
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
+	ports[1].enabled = 1;
+	SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser3, ss3extra);
+	SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync);
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA)
+	ports[1].use_dma = 1;
+	initialize_port(1);
+	if(request_irq(20, tr_interrupt, 0, "synchronous serial 3 dma tr", NULL))
+		panic("Can't allocate sync serial port 1 IRQ");
+	if(request_irq(21, rx_interrupt, 0, "synchronous serial 3 dma rx", NULL))
+		panic("Can't allocate sync serial port 1 IRQ");
+	RESET_DMA(4); WAIT_DMA(4);
+	RESET_DMA(5); WAIT_DMA(5);
+	*R_DMA_CH4_CLR_INTR = 3;  /* Clear IRQ */
+	*R_DMA_CH5_CLR_INTR = 3;  /* Clear IRQ */
+	*R_IRQ_MASK2_SET =
+	  IO_STATE(R_IRQ_MASK2_SET, dma4_eop, set) |
+	  IO_STATE(R_IRQ_MASK2_SET, dma4_descr, set) |
+	  IO_STATE(R_IRQ_MASK2_SET, dma5_eop, set) | 
+	  IO_STATE(R_IRQ_MASK2_SET, dma5_descr, set);
+	start_dma_in(&ports[1]);
+#else
+	ports[1].use_dma = 0;	
+	initialize_port(1);
+	if (port[0].use_dma) /* Port 0 uses dma, we must manual allocate IRQ */
+	{
+		if (request_irq(8, manual_interrupt, SA_SHIRQ, "synchronous serial manual irq", NULL))
+			panic("Can't allocate sync serial manual irq");
+	}
+	*R_IRQ_MASK1_SET = IO_STATE(R_IRQ_MASK1_SET, ser3_data, set);	 
+#endif
+#endif
+
+	*R_PORT_PB_I2C = port_pb_i2c_shadow; /* Use PB4/PB7 */
+
+	/* Set up timing */
+	*R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow = (
+	  IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec) | 
+	  IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u1, external) | 
+	  IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec) | 
+	  IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u3, external) | 
+	  IO_STATE(R_SYNC_SERIAL_PRESCALE, prescaler, div4) | 
+	  IO_FIELD(R_SYNC_SERIAL_PRESCALE, frame_rate, 0) | 
+	  IO_FIELD(R_SYNC_SERIAL_PRESCALE, word_rate, 7) | 
+	  IO_STATE(R_SYNC_SERIAL_PRESCALE, warp_mode, normal));
+
+	/* Select synchronous ports */
+	*R_GEN_CONFIG_II = gen_config_ii_shadow;
+
+	/*Initialize DMA flush timer if dma is used */
+	if (ports[0].use_dma || ports[1].use_dma) 
+	{
+		init_timer(&flush_timer);
+		flush_timer.function = flush_handler;
+		mod_timer(&flush_timer, jiffies + 10);
+	}
+
+	printk("Etrax100LX synchronous serial port driver\n");
+	return 0;
+}
+
+static void initialize_port(int portnbr)
+{
+	struct sync_port* port = &ports[portnbr];
+
+	DEBUG(printk("Init sync serial port %d\n", portnbr));
+    
+	port->port_nbr = portnbr;	
+	port->busy = 0;		
+	port->readp = port->in_buffer;
+	port->writep = port->in_buffer + IN_BUFFER_SIZE/2;
+	port->odd_input = 0;
+
+	init_waitqueue_head(&port->out_wait_q);
+	init_waitqueue_head(&port->in_wait_q);
+
+	port->ctrl_data_shadow =
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, tr_baud, c115k2Hz)   | 
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, mode, master_output) | 
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, error, ignore)       |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, rec_enable, disable) |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, f_synctype, normal)  |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, f_syncsize, word)    |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, f_sync, on)	     |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, clk_mode, normal)    |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, clk_halt, running)   |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, bitorder, msb)	     |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, tr_enable, enable)   |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit)  |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, buf_empty, lmt_8)    |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, buf_full, lmt_8)     |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled)  |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, clk_polarity, neg)   |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, frame_polarity, normal)|
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, status_polarity, inverted)|
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, clk_driver, normal)   |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, frame_driver, normal) |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, status_driver, normal)|
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, def_out0, high);
+  
+	if (port->use_dma)
+		port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL, dma_enable, on);
+	else
+		port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL, dma_enable, off);
+  
+	*port->ctrl_data = port->ctrl_data_shadow;
+}
+
+static int sync_serial_open(struct inode *inode, struct file *file)
+{
+	int dev = MINOR(inode->i_rdev);
+	DEBUG(printk("Open sync serial port %d\n", dev)); 
+  
+	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+	{
+		DEBUG(printk("Invalid minor %d\n", dev));
+		return -ENODEV;
+	}
+	if (ports[dev].busy)
+	{
+		DEBUG(printk("Device is busy.. \n"));
+		return -EBUSY;
+	}
+	ports[dev].busy = 1;
+	return 0;
+}
+
+static int sync_serial_release(struct inode *inode, struct file *file)
+{
+	ports[MINOR(inode->i_rdev)].busy = 0;
+	return 0;
+}
+
+static int sync_serial_ioctl(struct inode *inode, struct file *file,
+		  unsigned int cmd, unsigned long arg)
+{
+	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+	sync_port* port = &ports[dev];
+
+	/* Disable port while changing config */
+	if (dev)
+	{
+		RESET_DMA(4); WAIT_DMA(4);
+		*R_DMA_CH4_CLR_INTR = 3;  
+		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
+	}
+	else
+	{
+		RESET_DMA(8); WAIT_DMA(8);
+		*R_DMA_CH8_CLR_INTR = 3;  
+		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
+	}
+	*R_GEN_CONFIG_II = gen_config_ii_shadow;
+
+	switch(cmd)
+	{
+		case SSP_SPEED:
+			if (GET_SPEED(arg) == CODEC)
+			{
+				if (dev)
+					SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec);
+				else
+					SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec);
+
+				SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, prescaler, GET_FREQ(arg));
+				SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, frame_rate, GET_FRAME_RATE(arg));
+				SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, word_rate, GET_WORD_RATE(arg));
+			}
+			else
+			{
+				SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_baud, GET_SPEED(arg));
+				if (dev)
+					SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, baudrate);
+				else
+					SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, baudrate);
+			}
+			break;
+		case SSP_MODE:
+			if (arg > 5)
+				return -EINVAL;
+			SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, arg);
+			break;
+		case SSP_FRAME_SYNC:
+			if (arg & NORMAL_SYNC)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, normal);
+			else if (arg & EARLY_SYNC)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, early);
+    
+			if (arg & BIT_SYNC)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, bit);
+			else if (arg & WORD_SYNC)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);
+			else if (arg & EXTENDED_SYNC)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, extended);
+    
+			if (arg & SYNC_ON)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);
+			else if (arg & SYNC_OFF)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, off);
+    
+			if (arg & WORD_SIZE_8)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);
+			else if (arg & WORD_SIZE_12)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size12bit);
+			else if (arg & WORD_SIZE_16)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size16bit);
+			else if (arg & WORD_SIZE_24)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size24bit);
+			else if (arg & WORD_SIZE_32)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size32bit);
+    
+			if (arg & BIT_ORDER_MSB)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);
+			else if (arg & BIT_ORDER_LSB)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, lsb);
+
+			if (arg & FLOW_CONTROL_ENABLE)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled);
+			else if (arg & FLOW_CONTROL_DISABLE)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);
+
+			if (arg & CLOCK_NOT_GATED)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, normal);
+			else if (arg & CLOCK_GATED)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, gated);
+    
+			break;
+		case SSP_IPOLARITY:
+			if (arg & CLOCK_NORMAL)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);
+			else if (arg & CLOCK_INVERT)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, pos);
+
+			if (arg & FRAME_NORMAL)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, normal);
+			else if (arg & FRAME_INVERT)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);
+
+			if (arg & STATUS_NORMAL)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, normal);
+			else if (arg & STATUS_INVERT)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, inverted);
+			break;
+		case SSP_OPOLARITY:
+			if (arg & CLOCK_NORMAL)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, normal);
+			else if (arg & CLOCK_INVERT)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);
+    
+			if (arg & FRAME_NORMAL)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, normal);
+			else if (arg & FRAME_INVERT)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);
+
+			if (arg & STATUS_NORMAL)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, normal);
+			else if (arg & STATUS_INVERT)
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, inverted);
+			break;
+		case SSP_SPI:
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, normal);
+			if (arg & SPI_SLAVE)
+			{
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);
+				SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, SLAVE_INPUT);
+			}
+			else
+			{
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);
+				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);
+				SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, MASTER_OUTPUT);
+			}
+			break;
+		default:
+			return -EINVAL;
+	}
+	/* Set config and enable port */
+	*port->ctrl_data = port->ctrl_data_shadow;
+	*R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow;
+	if (dev)
+		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync);
+	else
+		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
+
+	*R_GEN_CONFIG_II = gen_config_ii_shadow;
+	return 0;
+}
+
+static ssize_t sync_serial_manual_write(struct file * file, const char * buf, 
+                                        size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	sync_port* port = &ports[MINOR(file->f_dentry->d_inode->i_rdev)];
+
+	copy_from_user(port->out_buffer, buf, count);
+	port->outp = port->out_buffer;
+	port->out_count = count;
+	port->odd_output = 1;
+	add_wait_queue(&port->out_wait_q, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	*R_IRQ_MASK1_SET = 1 << port->ready_irq_bit; /* transmitter ready IRQ on */
+	send_word(port); /* Start sender by sending first word */
+	schedule();
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&port->out_wait_q, &wait);
+	return count;
+}
+
+static ssize_t sync_serial_write(struct file * file, const char * buf, 
+                                 size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	sync_port *port = &ports[MINOR(file->f_dentry->d_inode->i_rdev)];
+
+	DEBUG(printk("Write dev %d count %d\n", port->port_nbr, count));
+
+	if (!port->use_dma)
+	{
+		return sync_serial_manual_write(file, buf, count, ppos); 
+	}
+  
+	copy_from_user(port->out_buffer, buf, count);
+	add_wait_queue(&port->out_wait_q, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	start_dma(port, buf, count);
+	schedule();
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&port->out_wait_q, &wait);
+	return count;
+}
+
+static ssize_t sync_serial_read(struct file * file, char * buf, 
+				size_t count, loff_t *ppos)
+{
+	int avail;
+	sync_port *port = &ports[MINOR(file->f_dentry->d_inode->i_rdev)];
+	char* start; 
+	char* end;
+	unsigned long flags;	
+
+	DEBUG(printk("Read dev %d count\n"));
+
+	/* Calculate number of available bytes */
+	while (port->readp == port->writep) /* No data */
+	{
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+			interruptible_sleep_on(&port->in_wait_q);
+	}
+	
+	/* Save pointers to avoid that they are modified by interrupt */
+	start = port->readp;
+	end = port->writep;
+
+	/* Lazy read, never return wrapped data. */
+	if (end > start)
+		avail = end - start;
+	else 
+		avail = port->in_buffer + IN_BUFFER_SIZE - start;
+  
+	count = count > avail ? avail : count;
+	copy_to_user(buf, start, count);
+
+	/* Disable interrupts while updating readp */
+	save_flags(flags);
+	cli();	
+	port->readp += count;
+	if (port->readp == port->in_buffer + IN_BUFFER_SIZE) /* Wrap? */
+		port->readp = port->in_buffer;
+	restore_flags(flags);
+
+	DEBUG(printk("%d bytes read\n", count));
+	return count;
+}
+
+static void send_word(sync_port* port)
+{
+	switch(port->ctrl_data_shadow & IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize))
+	{
+		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
+			port->out_count--;
+			*port->data_out = *port->outp++;
+			break;
+		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
+			port->out_count--;
+			if (port->odd_output)
+				*port->data_out = ((*port->outp) << 16) | (*(unsigned short *)(port->outp + 1));
+			else
+				*port->data_out = ((*(unsigned short *)port->outp) << 8) | (*(port->outp + 1));
+			port->odd_output = !port->odd_output;
+			port->outp++;
+			break;
+		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
+			port->out_count-=2;
+			*port->data_out = *(unsigned short *)port->outp;
+			port->outp+=2;
+			break;
+		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
+			port->out_count-=3;
+			*port->data_out = *(unsigned int *)port->outp;
+			port->outp+=3;
+			break;
+		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
+			port->out_count-=4;
+			*port->data_out = *(unsigned int *)port->outp;
+			port->outp+=4;
+			break;
+	}
+}
+
+static void start_dma(struct sync_port* port, const char* data, int count)
+{
+	port->out_descr.hw_len = 0;
+	port->out_descr.next = 0;
+	port->out_descr.ctrl = d_int | d_eol | d_eop;
+	port->out_descr.sw_len = count;
+	port->out_descr.buf = virt_to_phys(port->out_buffer);
+	port->out_descr.status = 0;
+
+	*port->output_dma_first = virt_to_phys(&port->out_descr);
+	*port->output_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);
+}
+
+static void start_dma_in(sync_port* port)
+{
+	if (port->writep > port->in_buffer + IN_BUFFER_SIZE)
+	{
+		panic("Offset too large in sync serial driver\n");
+		return;
+	}
+	port->in_descr1.hw_len = 0;
+	port->in_descr1.ctrl = d_eop | d_int;
+	port->in_descr1.status = 0;
+	port->in_descr1.next = virt_to_phys(&port->in_descr2);
+	port->in_descr2.hw_len = 0;
+	port->in_descr2.next = virt_to_phys(&port->in_descr1);
+	port->in_descr2.ctrl = d_eop | d_int;
+	port->in_descr2.status = 0;
+
+	/* Find out which descriptor to start */
+	if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2)
+	{
+		/* Start descriptor 2 */
+		port->in_descr1.sw_len = IN_BUFFER_SIZE/2; /* All data available in 1 */
+		port->in_descr1.buf = virt_to_phys(port->in_buffer);
+		port->in_descr2.sw_len = port->in_buffer + IN_BUFFER_SIZE - port->writep;
+		port->in_descr2.buf = virt_to_phys(port->writep);
+		*port->input_dma_first = virt_to_phys(&port->in_descr2);
+	}
+	else
+	{
+		/* Start descriptor 1 */
+		port->in_descr1.sw_len = port->in_buffer + IN_BUFFER_SIZE/2 - port->writep;
+		port->in_descr1.buf = virt_to_phys(port->writep);
+		port->in_descr2.sw_len = IN_BUFFER_SIZE/2;
+		port->in_descr2.buf = virt_to_phys(port->in_buffer + IN_BUFFER_SIZE / 2);
+		*port->input_dma_first = virt_to_phys(&port->in_descr1);
+	}
+	*port->input_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);
+}
+
+static void tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	unsigned long ireg = *R_IRQ_MASK2_RD;
+	int i;
+
+	for (i = 0; i < NUMBER_OF_PORTS; i++) 
+	{
+		sync_port *port = &ports[i];
+		if (ireg & (1 << port->output_dma_bit)) /* IRQ active for the port? */
+		{
+			/* Clear IRQ */
+			*port->output_dma_clr_irq = 
+			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) |
+			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);
+			wake_up_interruptible(&port->out_wait_q); /* wake up the waiting process */
+		} 
+	}
+}
+
+static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	unsigned long ireg = *R_IRQ_MASK2_RD;
+	int i;	
+
+	for (i = 0; i < NUMBER_OF_PORTS; i++) 
+	{
+		int update = 0;
+		sync_port *port = &ports[i];
+
+		if (!port->enabled)
+		{
+			continue;
+		}    
+
+		if (ireg & (1 << port->input_dma_descr_bit)) /* Descriptor interrupt */
+		{
+			/* DMA has reached end of descriptor */
+			*port->input_dma_clr_irq = 
+			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) | 
+			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);
+
+			/* Find out which descriptor that is ready */
+			if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2) 
+			{
+				/* Descr 2 was ready. Restart DMA at descriptor 1 */
+				port->writep = port->in_buffer;
+	
+				/* Throw away data? */
+				if (port->readp < port->in_buffer + IN_BUFFER_SIZE/2)
+					port->readp = port->in_buffer + IN_BUFFER_SIZE/2;
+			}
+			else
+			{
+				/* Descr 1 was ready. Restart DMA at descriptor 2 */
+				port->writep = port->in_buffer + IN_BUFFER_SIZE/2;
+
+				/* Throw away data? */
+				if (port->readp >= port->in_buffer + IN_BUFFER_SIZE/2)
+					port->readp = port->in_buffer;
+			}
+			start_dma_in(port);
+			wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */
+		}
+		else if (ireg & (1 << port->input_dma_eop_bit)) /* EOP interrupt */
+		{
+			/* EOP interrupt means that DMA has not reached end of descriptor */
+			*port->input_dma_clr_irq = 
+			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) | 
+			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);
+
+			/* Find out the current descriptor */
+			if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2)
+				port->writep += port->in_descr2.hw_len;
+			else
+				port->writep += port->in_descr1.hw_len;
+
+			start_dma_in(port);
+			wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */
+		}
+	}
+}
+
+static void manual_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	int i;
+
+	for (i = 0; i < NUMBER_OF_PORTS; i++)
+	{
+		sync_port* port = &ports[i];
+
+		if (!port->enabled)
+		{
+			continue;
+		}
+
+		if (*R_IRQ_MASK1_RD & (1 << port->data_avail_bit))	/* Data received? */
+		{
+			/* Read data */
+			switch(port->ctrl_data_shadow & IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize))
+			{
+				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
+					*port->writep++ = *(volatile char *)port->data_in;
+					break;
+				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
+				{
+					int data = *(unsigned short *)port->data_in;
+					if (port->odd_input)
+					{
+						*port->writep |= (data & 0x0f00) >> 8;
+						*(port->writep + 1) = data & 0xff;
+					}
+					else
+					{
+						*port->writep = (data & 0x0ff0) >> 4;
+						*(port->writep + 1) = (data & 0x0f) << 4;
+					}
+					port->odd_input = !port->odd_input;
+					port->writep+=1;
+				}
+				break;
+				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
+					*(unsigned short*)port->writep = *(volatile unsigned short *)port->data_in;
+					port->writep+=2;
+					break;
+				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
+					*(unsigned int*)port->writep = *port->data_in;
+					port->writep+=3;
+					break;
+				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
+					*(unsigned int*)port->writep = *port->data_in;
+					port->writep+=4;
+					break;
+			}
+
+			if (port->writep > port->in_buffer + IN_BUFFER_SIZE) /* Wrap? */
+				port->writep = port->in_buffer;
+			wake_up_interruptible(&port->in_wait_q); /* Wake up application */
+		}
+
+		if (*R_IRQ_MASK1_RD & (1 << port->transmitter_ready_bit)) /* Transmitter ready? */
+		{
+			if (port->out_count) /* More data to send */
+				send_word(port);
+			else /* transmission finished */
+			{
+				*R_IRQ_MASK1_CLR = 1 << port->ready_irq_bit; /* Turn off IRQ */
+				wake_up_interruptible(&port->out_wait_q); /* Wake up application */
+			}
+		}
+	}
+}
+
+static void flush_handler(void)
+{
+	int i;
+	
+	for (i = 0; i < NUMBER_OF_PORTS; i++)
+	{
+		if (ports[i].enabled)
+		{
+			*R_SET_EOP = 1 << ports[i].eop_bit;  
+		}
+	}
+	/* restart flush timer */
+	mod_timer(&flush_timer, jiffies + 10);
+}
+
+module_init(etrax_sync_serial_init);
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/usb-host.c linux/arch/cris/drivers/usb-host.c
--- v2.4.3/linux/arch/cris/drivers/usb-host.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/usb-host.c	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,2501 @@
+/*
+ * usb-host.c: ETRAX 100LX USB Host Controller Driver (HCD)
+ *
+ * Copyright (c) 2001 Axis Communications AB.
+ *
+ * $Id: usb-host.c,v 1.8 2001/02/27 13:52:48 bjornw Exp $
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/list.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/svinto.h>
+
+#include <linux/usb.h>
+#include "usb-host.h"
+
+#define ETRAX_USB_HC_IRQ 31
+#define ETRAX_USB_RX_IRQ 25
+#define ETRAX_USB_TX_IRQ 24
+
+static const char *usb_hcd_version = "$Revision: 1.8 $";
+
+#undef KERN_DEBUG
+#define KERN_DEBUG ""
+
+#undef USB_DEBUG_RH
+#undef USB_DEBUG_EP
+#undef USB_DEBUG_DESC
+#undef USB_DEBUG_TRACE
+#undef USB_DEBUG_CTRL
+#undef USB_DEBUG_BULK
+#undef USB_DEBUG_INTR
+
+#ifdef USB_DEBUG_RH
+#define dbg_rh(format, arg...) printk(KERN_DEBUG __FILE__ ": (RH) " format "\n" , ## arg)
+#else
+#define dbg_rh(format, arg...) do {} while (0)
+#endif
+
+#ifdef USB_DEBUG_EP
+#define dbg_ep(format, arg...) printk(KERN_DEBUG __FILE__ ": (EP) " format "\n" , ## arg)
+#else
+#define dbg_ep(format, arg...) do {} while (0)
+#endif
+
+#ifdef USB_DEBUG_CTRL
+#define dbg_ctrl(format, arg...) printk(KERN_DEBUG __FILE__ ": (CTRL) " format "\n" , ## arg)
+#else
+#define dbg_ctrl(format, arg...) do {} while (0)
+#endif
+
+#ifdef USB_DEBUG_BULK
+#define dbg_bulk(format, arg...) printk(KERN_DEBUG __FILE__ ": (BULK) " format "\n" , ## arg)
+#else
+#define dbg_bulk(format, arg...) do {} while (0)
+#endif
+
+#ifdef USB_DEBUG_INTR
+#define dbg_intr(format, arg...) printk(KERN_DEBUG __FILE__ ": (INTR) " format "\n" , ## arg)
+#else
+#define dbg_intr(format, arg...) do {} while (0)
+#endif
+
+#ifdef USB_DEBUG_TRACE
+#define DBFENTER (printk(KERN_DEBUG __FILE__ ": Entering : " __FUNCTION__ "\n"))
+#define DBFEXIT  (printk(KERN_DEBUG __FILE__ ": Exiting  : " __FUNCTION__ "\n"))
+#else
+#define DBFENTER (NULL)
+#define DBFEXIT  (NULL)
+#endif
+
+/*-------------------------------------------------------------------
+ Virtual Root Hub
+ -------------------------------------------------------------------*/
+
+static __u8 root_hub_dev_des[] =
+{
+	0x12,  /*  __u8  bLength; */
+	0x01,  /*  __u8  bDescriptorType; Device */
+	0x00,  /*  __u16 bcdUSB; v1.0 */
+	0x01,
+	0x09,  /*  __u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,  /*  __u8  bDeviceSubClass; */
+	0x00,  /*  __u8  bDeviceProtocol; */
+	0x08,  /*  __u8  bMaxPacketSize0; 8 Bytes */
+	0x00,  /*  __u16 idVendor; */
+	0x00,
+	0x00,  /*  __u16 idProduct; */
+	0x00,
+	0x00,  /*  __u16 bcdDevice; */
+	0x00,
+	0x00,  /*  __u8  iManufacturer; */
+	0x02,  /*  __u8  iProduct; */
+	0x01,  /*  __u8  iSerialNumber; */
+	0x01   /*  __u8  bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+	0x09,  /*  __u8  bLength; */
+	0x02,  /*  __u8  bDescriptorType; Configuration */
+	0x19,  /*  __u16 wTotalLength; */
+	0x00,
+	0x01,  /*  __u8  bNumInterfaces; */
+	0x01,  /*  __u8  bConfigurationValue; */
+	0x00,  /*  __u8  iConfiguration; */
+	0x40,  /*  __u8  bmAttributes; Bit 7: Bus-powered */
+	0x00,  /*  __u8  MaxPower; */
+
+     /* interface */
+	0x09,  /*  __u8  if_bLength; */
+	0x04,  /*  __u8  if_bDescriptorType; Interface */
+	0x00,  /*  __u8  if_bInterfaceNumber; */
+	0x00,  /*  __u8  if_bAlternateSetting; */
+	0x01,  /*  __u8  if_bNumEndpoints; */
+	0x09,  /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,  /*  __u8  if_bInterfaceSubClass; */
+	0x00,  /*  __u8  if_bInterfaceProtocol; */
+	0x00,  /*  __u8  if_iInterface; */
+
+     /* endpoint */
+	0x07,  /*  __u8  ep_bLength; */
+	0x05,  /*  __u8  ep_bDescriptorType; Endpoint */
+	0x81,  /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+	0x03,  /*  __u8  ep_bmAttributes; Interrupt */
+	0x08,  /*  __u16 ep_wMaxPacketSize; 8 Bytes */
+	0x00,
+	0xff   /*  __u8  ep_bInterval; 255 ms */
+};
+
+static __u8 root_hub_hub_des[] =
+{
+	0x09,  /*  __u8  bLength; */
+	0x29,  /*  __u8  bDescriptorType; Hub-descriptor */
+	0x02,  /*  __u8  bNbrPorts; */
+	0x00,  /* __u16  wHubCharacteristics; */
+	0x00,
+	0x01,  /*  __u8  bPwrOn2pwrGood; 2ms */
+	0x00,  /*  __u8  bHubContrCurrent; 0 mA */
+	0x00,  /*  __u8  DeviceRemovable; *** 7 Ports max *** */
+	0xff   /*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
+};
+
+
+#define OK(x) len = (x); dbg_rh("OK(%d): line: %d", x, __LINE__); break
+#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \
+{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);}
+
+static submit_urb_count = 0;
+
+//#define ETRAX_USB_INTR_IRQ
+//#define ETRAX_USB_INTR_ERROR_FATAL
+
+#define RX_BUF_SIZE        32768
+#define RX_DESC_BUF_SIZE   64
+#define NBR_OF_RX_DESC     (RX_BUF_SIZE / RX_DESC_BUF_SIZE)
+
+#define NBR_OF_EP_DESC     32
+
+#define MAX_INTR_INTERVAL 128
+
+static __u32 ep_usage_bitmask;
+static __u32 ep_really_active;
+
+static unsigned char RxBuf[RX_BUF_SIZE];
+static USB_IN_Desc_t RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned (4)));
+
+static volatile USB_IN_Desc_t *myNextRxDesc;
+static volatile USB_IN_Desc_t *myLastRxDesc;
+static volatile USB_IN_Desc_t *myPrevRxDesc;
+
+static USB_EP_Desc_t TxCtrlEPList[NBR_OF_EP_DESC] __attribute__ ((aligned (4)));
+static USB_EP_Desc_t TxBulkEPList[NBR_OF_EP_DESC] __attribute__ ((aligned (4)));
+
+static USB_EP_Desc_t TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4)));
+static USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4)));
+
+static urb_t *URB_List[NBR_OF_EP_DESC];
+static kmem_cache_t *usb_desc_cache;
+static struct usb_bus *etrax_usb_bus;
+
+static void dump_urb (purb_t purb);
+static void init_rx_buffers(void);
+static int etrax_rh_unlink_urb (urb_t *urb);
+static void etrax_rh_send_irq(urb_t *urb);
+static void etrax_rh_init_int_timer(urb_t *urb);
+static void etrax_rh_int_timer_do(unsigned long ptr);
+
+static void etrax_usb_setup_epid(char epid, char devnum, char endpoint,
+				 char packsize, char slow);
+static int etrax_usb_lookup_epid(unsigned char devnum, char endpoint, char slow, int maxp);
+static int etrax_usb_allocate_epid(void);
+static void etrax_usb_free_epid(char epid);
+static void cleanup_sb(USB_SB_Desc_t *sb);
+
+static int etrax_usb_do_ctrl_hw_add(urb_t *urb, char epid, char maxlen);
+static int etrax_usb_do_bulk_hw_add(urb_t *urb, char epid, char maxlen);
+
+static int etrax_usb_submit_ctrl_urb(urb_t *urb);
+
+static int etrax_usb_submit_urb(urb_t *urb);
+static int etrax_usb_unlink_urb(urb_t *urb);
+static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
+static int etrax_usb_allocate_dev(struct usb_device *usb_dev);
+static int etrax_usb_deallocate_dev(struct usb_device *usb_dev);
+
+static void etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs);
+static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs);
+static void etrax_usb_hc_intr_top_half(int irq, void *vhc, struct pt_regs *regs);
+
+static int etrax_rh_submit_urb (urb_t *urb);
+
+static int etrax_usb_hc_init(void);
+static void etrax_usb_hc_cleanup(void);
+
+static struct usb_operations etrax_usb_device_operations =
+{
+	etrax_usb_allocate_dev,
+	etrax_usb_deallocate_dev,
+	etrax_usb_get_frame_number,
+	etrax_usb_submit_urb,
+	etrax_usb_unlink_urb
+};
+
+#ifdef USB_DEBUG_DESC
+static void dump_urb(purb_t purb)
+{
+	printk("\nurb                   :0x%08X\n", purb);
+	printk("next                  :0x%08X\n", purb->next);
+	printk("dev                   :0x%08X\n", purb->dev);
+	printk("pipe                  :0x%08X\n", purb->pipe);
+	printk("status                :%d\n", purb->status);
+	printk("transfer_flags        :0x%08X\n", purb->transfer_flags);
+	printk("transfer_buffer       :0x%08X\n", purb->transfer_buffer);
+	printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
+	printk("actual_length         :%d\n", purb->actual_length);
+	printk("setup_packet          :0x%08X\n", purb->setup_packet);
+	printk("start_frame           :%d\n", purb->start_frame);
+	printk("number_of_packets     :%d\n", purb->number_of_packets);
+	printk("interval              :%d\n", purb->interval);
+	printk("error_count           :%d\n", purb->error_count);
+	printk("context               :0x%08X\n", purb->context);
+	printk("complete              :0x%08X\n\n", purb->complete);
+}
+
+static void dump_in_desc(USB_IN_Desc_t *in)
+{
+	printk("\nUSB_IN_Desc at 0x%08X\n", in);
+	printk("  sw_len  : 0x%04X (%d)\n", in->sw_len, in->sw_len);
+	printk("  command : 0x%04X\n", in->command);
+	printk("  next    : 0x%08X\n", in->next);
+	printk("  buf     : 0x%08X\n", in->buf);
+	printk("  hw_len  : 0x%04X (%d)\n", in->hw_len, in->hw_len);
+	printk("  status  : 0x%04X\n\n", in->status);
+}
+
+static void dump_sb_desc(USB_SB_Desc_t *sb)
+{
+	printk("\nUSB_SB_Desc at 0x%08X\n", sb);
+	printk("  sw_len  : 0x%04X (%d)\n", sb->sw_len, sb->sw_len);
+	printk("  command : 0x%04X\n", sb->command);
+	printk("  next    : 0x%08X\n", sb->next);
+	printk("  buf     : 0x%08X\n\n", sb->buf);
+}
+
+
+static void dump_ep_desc(USB_EP_Desc_t *ep)
+{
+	printk("\nUSB_EP_Desc at 0x%08X\n", ep);
+	printk("  hw_len  : 0x%04X (%d)\n", ep->hw_len, ep->hw_len);
+	printk("  command : 0x%08X\n", ep->command);
+	printk("  sub     : 0x%08X\n", ep->sub);
+	printk("  nep     : 0x%08X\n\n", ep->nep);
+}
+
+
+#else
+#define dump_urb(...)     (NULL)
+#define dump_ep_desc(...) (NULL)
+#define dump_sb_desc(...) (NULL)
+#define dump_in_desc(...) (NULL)
+#endif
+
+static void init_rx_buffers(void)
+{
+	int i;
+	
+	DBFENTER;
+	
+	for (i = 0; i < (NBR_OF_RX_DESC - 1); i++) {
+		RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
+		RxDescList[i].command = 0;
+		RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]);
+		RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));
+		RxDescList[i].hw_len = 0;
+		RxDescList[i].status = 0;
+	}
+	
+	RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
+	RxDescList[i].command = IO_STATE(USB_IN_command, eol, yes);
+	RxDescList[i].next = virt_to_phys(&RxDescList[0]);
+	RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));
+	RxDescList[i].hw_len = 0;
+	RxDescList[i].status = 0;
+
+	myNextRxDesc = &RxDescList[0];
+	myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
+	myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
+
+	*R_DMA_CH9_FIRST = virt_to_phys(myNextRxDesc);
+	*R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, start);
+	
+	DBFEXIT;
+}
+
+static void init_tx_ctrl_ep(void)
+{
+	int i;
+	
+	DBFENTER;
+	
+	for (i = 0; i < (NBR_OF_EP_DESC - 1); i++) {
+		TxCtrlEPList[i].hw_len = 0;
+		TxCtrlEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
+		TxCtrlEPList[i].sub = 0;
+		TxCtrlEPList[i].nep = virt_to_phys(&TxCtrlEPList[i + 1]);
+	}
+	
+	TxCtrlEPList[i].hw_len = 0;
+	TxCtrlEPList[i].command = IO_STATE(USB_EP_command, eol, yes) |
+		IO_FIELD(USB_EP_command, epid, i);
+
+	TxCtrlEPList[i].sub = 0;
+	TxCtrlEPList[i].nep = virt_to_phys(&TxCtrlEPList[0]);
+	
+	*R_DMA_CH8_SUB1_EP = virt_to_phys(&TxCtrlEPList[0]);
+	*R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);
+	
+	DBFEXIT;
+}
+
+static void init_tx_bulk_ep(void)
+{
+	int i;
+	
+	DBFENTER;
+	
+	for (i = 0; i < (NBR_OF_EP_DESC - 1); i++) {
+		TxBulkEPList[i].hw_len = 0;
+		TxBulkEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
+		TxBulkEPList[i].sub = 0;
+		TxBulkEPList[i].nep = virt_to_phys(&TxBulkEPList[i + 1]);
+	}
+	
+	TxBulkEPList[i].hw_len = 0;
+	TxBulkEPList[i].command = IO_STATE(USB_EP_command, eol, yes) |
+		IO_FIELD(USB_EP_command, epid, i);
+
+	TxBulkEPList[i].sub = 0;
+	TxBulkEPList[i].nep = virt_to_phys(&TxBulkEPList[0]);
+	
+	*R_DMA_CH8_SUB0_EP = virt_to_phys(&TxBulkEPList[0]);
+	*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);
+	
+	DBFEXIT;
+}
+
+static void init_tx_intr_ep(void)
+{
+	int i;
+
+	DBFENTER;
+
+	TxIntrSB_zout.sw_len = 0;
+	TxIntrSB_zout.next = 0;
+	TxIntrSB_zout.buf = 0;
+	TxIntrSB_zout.command = IO_FIELD(USB_SB_command, rem, 0) |
+		IO_STATE(USB_SB_command, tt, zout) |
+		IO_STATE(USB_SB_command, full, yes) |
+		IO_STATE(USB_SB_command, eot, yes) |
+		IO_STATE(USB_SB_command, eol, yes);
+
+	for (i = 0; i < (MAX_INTR_INTERVAL - 1); i++) {
+		TxIntrEPList[i].hw_len = 0;
+		TxIntrEPList[i].command = IO_STATE(USB_EP_command, eof, yes) |
+			IO_STATE(USB_EP_command, enable, yes) |
+			IO_FIELD(USB_EP_command, epid, 0);
+		TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);
+		TxIntrEPList[i].nep = virt_to_phys(&TxIntrEPList[i + 1]);
+	}
+	
+	TxIntrEPList[i].hw_len = 0;
+	TxIntrEPList[i].command =
+		IO_STATE(USB_EP_command, eof, yes) |
+		IO_STATE(USB_EP_command, enable, yes) |
+		IO_FIELD(USB_EP_command, epid, 0);
+	TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);
+	TxIntrEPList[i].nep = virt_to_phys(&TxIntrEPList[0]);
+
+	*R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]);
+	*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
+	
+	DBFEXIT;
+}
+
+
+static int etrax_usb_unlink_intr_urb(urb_t *urb)
+{
+	struct usb_device *usb_dev = urb->dev;
+	etrax_hc_t *hc = usb_dev->bus->hcpriv;
+
+	USB_EP_Desc_t *tmp_ep;
+	USB_EP_Desc_t *first_ep;
+	
+	USB_EP_Desc_t *ep_desc;
+	USB_SB_Desc_t *sb_desc;
+	
+	char epid;
+	char devnum;
+	char endpoint;
+	char slow;
+	int maxlen;
+	int i;
+	
+	etrax_urb_priv_t *urb_priv;
+	unsigned long flags;
+	
+	DBFENTER;
+
+	devnum = usb_pipedevice(urb->pipe);
+	endpoint = usb_pipeendpoint(urb->pipe);
+	slow = usb_pipeslow(urb->pipe);
+	maxlen = usb_maxpacket(urb->dev, urb->pipe,
+			       usb_pipeout(urb->pipe));
+
+	epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
+	if (epid == -1) {
+		err("Trying to unlink urb that is not in traffic queue!!");
+		return -1;  /* fix this */
+	}
+
+	*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, stop);
+	/* Somehow wait for the DMA to finish current activities */
+	i = jiffies + 100;
+	while (jiffies < i);	
+	
+	first_ep = &TxIntrEPList[0];
+	tmp_ep = first_ep;
+	
+	do {
+		if (IO_EXTRACT(USB_EP_command, epid, ((USB_EP_Desc_t *)phys_to_virt(tmp_ep->nep))->command)
+		    == epid) {
+			/* Unlink it !!! */
+			dbg_intr("Found urb to unlink for epid %d", epid);
+			
+			ep_desc = phys_to_virt(tmp_ep->nep);
+			tmp_ep->nep = ep_desc->nep;
+			kmem_cache_free(usb_desc_cache, phys_to_virt(ep_desc->sub));
+			kmem_cache_free(usb_desc_cache, ep_desc);
+		}
+
+		tmp_ep = phys_to_virt(tmp_ep->nep);
+		
+	} while (tmp_ep != first_ep);
+
+	/* We should really try to move the EP register to an EP that is not removed
+	   instead of restarting, but this will work too */
+	*R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]);
+	*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
+
+	clear_bit(epid, (void *)&ep_really_active);
+	URB_List[epid] = NULL;
+	etrax_usb_free_epid(epid);
+	
+	DBFEXIT;
+
+	return 0;
+}
+
+void etrax_usb_do_intr_recover(int epid)
+{
+	USB_EP_Desc_t *first_ep, *tmp_ep;
+	
+	first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP);
+	tmp_ep = first_ep;
+
+	do {
+		if (IO_EXTRACT(USB_EP_command, epid, tmp_ep->command) == epid &&
+		    !(tmp_ep->command & IO_MASK(USB_EP_command, enable))) {
+			tmp_ep->command |= IO_STATE(USB_EP_command, enable, yes);
+		}
+		
+		tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->nep);
+		
+	} while (tmp_ep != first_ep);
+}
+
+static int etrax_usb_submit_intr_urb(urb_t *urb)
+{
+	USB_EP_Desc_t *tmp_ep;
+	USB_EP_Desc_t *first_ep;
+	
+	USB_SB_Desc_t *sb_desc;
+	
+	char epid;
+	char devnum;
+	char endpoint;
+	char maxlen;
+	char slow;
+	int interval;
+	int i;
+	
+	etrax_urb_priv_t *urb_priv;
+	unsigned long flags;
+	
+	DBFENTER;
+
+	devnum = usb_pipedevice(urb->pipe);
+	endpoint = usb_pipeendpoint(urb->pipe);
+	maxlen = usb_maxpacket(urb->dev, urb->pipe,
+			       usb_pipeout(urb->pipe));
+
+	slow = usb_pipeslow(urb->pipe);
+	interval = urb->interval;
+
+	dbg_intr("Intr traffic for dev %d, endpoint %d, maxlen %d, slow %d",
+		 devnum, endpoint, maxlen, slow);
+	
+	epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
+	if (epid == -1) {
+		epid = etrax_usb_allocate_epid();
+		if (epid == -1) {
+			/* We're out of endpoints, return some error */
+			err("We're out of endpoints");
+			return -ENOMEM;
+		}
+		/* Now we have to fill in this ep */
+		etrax_usb_setup_epid(epid, devnum, endpoint, maxlen, slow);
+	}
+	/* Ok, now we got valid endpoint, lets insert some traffic */
+
+	urb_priv = (etrax_urb_priv_t *)kmalloc(sizeof(etrax_urb_priv_t), GFP_KERNEL);
+	urb_priv->first_sb = 0;
+	urb_priv->rx_offset = 0;
+	urb_priv->eot = 0;
+	INIT_LIST_HEAD(&urb_priv->ep_in_list);
+	urb->hcpriv = urb_priv;
+
+	/* This is safe since there cannot be any other URB's for this epid */
+	URB_List[epid] = urb;
+#if 0
+	first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP);
+#else
+	first_ep = &TxIntrEPList[0];
+#endif
+
+	/* Round of the interval to 2^n, it is obvious that this code favours
+	   smaller numbers, but that is actually a good thing */
+	for (i = 0; interval; i++) {
+		interval = interval >> 1;
+	}
+
+	urb->interval = interval = 1 << (i - 1);
+
+	dbg_intr("Interval rounded to %d", interval);
+
+	tmp_ep = first_ep;
+	i = 0;
+	do {
+		if (tmp_ep->command & IO_MASK(USB_EP_command, eof)) {
+			if ((i % interval) == 0) {
+				/* Insert the traffic ep after tmp_ep */
+				USB_EP_Desc_t *traffic_ep;
+				USB_SB_Desc_t *traffic_sb;
+
+				traffic_ep = (USB_EP_Desc_t *)
+					kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+				traffic_sb = (USB_SB_Desc_t *)
+					kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+
+				traffic_ep->hw_len = 0;
+				traffic_ep->command = IO_FIELD(USB_EP_command, epid, epid) |
+					IO_STATE(USB_EP_command, enable, yes);
+				traffic_ep->sub = virt_to_phys(traffic_sb);
+
+				if (usb_pipein(urb->pipe)) {
+					traffic_sb->sw_len = urb->transfer_buffer_length ?
+						(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
+					traffic_sb->next = 0;
+					traffic_sb->buf = 0;
+					traffic_sb->command = IO_FIELD(USB_SB_command, rem,
+								       urb->transfer_buffer_length % maxlen) |
+						IO_STATE(USB_SB_command, tt, in) |
+						IO_STATE(USB_SB_command, eot, yes) |
+						IO_STATE(USB_SB_command, eol, yes);
+					
+				} else if (usb_pipeout(urb->pipe)) {
+					traffic_sb->sw_len = urb->transfer_buffer_length;
+					traffic_sb->next = 0;
+					traffic_sb->buf = virt_to_phys(urb->transfer_buffer);
+					traffic_sb->command = IO_FIELD(USB_SB_command, rem, 0) |
+						IO_STATE(USB_SB_command, tt, out) |
+						IO_STATE(USB_SB_command, eot, yes) |
+						IO_STATE(USB_SB_command, eol, yes) |
+						IO_STATE(USB_SB_command, full, yes);
+				}
+
+				traffic_ep->nep = tmp_ep->nep;
+				tmp_ep->nep = virt_to_phys(traffic_ep);
+				dbg_intr("One ep successfully inserted");
+			}
+			i++;
+		}
+		tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->nep);
+	} while (tmp_ep != first_ep);
+
+	set_bit(epid, (void *)&ep_really_active);
+	
+	*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
+
+	DBFEXIT;
+	
+	return 0;
+}
+
+
+static int handle_intr_transfer_attn(char epid, int status)
+{
+	urb_t *old_urb;
+
+	DBFENTER;
+
+	old_urb = URB_List[epid];
+	
+	/* if (status == 0 && IN) find data and copy to urb */
+	if (status == 0 && usb_pipein(old_urb->pipe)) {
+		unsigned long flags;
+		etrax_urb_priv_t *urb_priv;
+		struct list_head *entry;
+		struct in_chunk *in;
+
+		urb_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
+		
+		save_flags(flags);
+		cli();
+
+		list_for_each(entry, &urb_priv->ep_in_list) {
+			in = list_entry(entry, struct in_chunk, list);
+			memcpy(old_urb->transfer_buffer, in->data, in->length);
+			old_urb->actual_length = in->length;
+			old_urb->status = status;
+			
+			if (old_urb->complete) {
+				old_urb->complete(old_urb);
+			}
+			
+			list_del(entry);
+			kfree(in->data);
+			kfree(in);
+		}		
+		
+		restore_flags(flags);
+
+	} else if (status != 0) {
+		warn("Some sort of error for INTR EP !!!!");
+#ifdef ETRAX_USB_INTR_ERROR_FATAL
+		/* This means that an INTR error is fatal for that endpoint */
+		etrax_usb_unlink_intr_urb(old_urb);
+		old_urb->status = status;
+		if (old_urb->complete) {
+			old_urb->complete(old_urb);
+		}
+#else
+		/* In this case we reenable the disabled endpoint(s) */
+		etrax_usb_do_intr_recover(epid);
+#endif	
+	}
+	
+	DBFEXIT;
+}
+
+static int etrax_rh_unlink_urb (urb_t *urb)
+{
+	etrax_hc_t *hc;
+	
+	DBFENTER;
+	
+	hc = urb->dev->bus->hcpriv;
+	
+	if (hc->rh.urb == urb) {
+		hc->rh.send = 0;
+		del_timer(&hc->rh.rh_int_timer);
+	}
+	
+	DBFEXIT;
+	return 0;
+}
+
+static void etrax_rh_send_irq(urb_t *urb)
+{
+	__u16 data = 0;
+	etrax_hc_t *hc = urb->dev->bus->hcpriv;
+//	static prev_wPortStatus_1 = 0;
+//	static prev_wPortStatus_2 = 0;
+	
+/*	DBFENTER; */
+	
+	
+/*
+  dbg_rh("R_USB_FM_NUMBER   : 0x%08X", *R_USB_FM_NUMBER);
+  dbg_rh("R_USB_FM_REMAINING: 0x%08X", *R_USB_FM_REMAINING);
+*/
+	
+	data |= (hc->rh.wPortChange_1) ? (1 << 1) : 0;
+	data |= (hc->rh.wPortChange_2) ? (1 << 2) : 0;
+
+	*((__u16 *)urb->transfer_buffer) = cpu_to_le16(data);
+	urb->actual_length = 1;
+	urb->status = 0;
+
+	
+	if (data && hc->rh.send && urb->complete) {
+		dbg_rh("wPortChange_1: 0x%04X", hc->rh.wPortChange_1); 
+		dbg_rh("wPortChange_2: 0x%04X", hc->rh.wPortChange_2);
+
+		urb->complete(urb);
+	}
+  
+/*	DBFEXIT; */
+}
+
+static void etrax_rh_init_int_timer(urb_t *urb)
+{
+	etrax_hc_t *hc;
+	
+/*	DBFENTER; */
+	
+	hc = urb->dev->bus->hcpriv;
+	hc->rh.interval = urb->interval;
+	init_timer(&hc->rh.rh_int_timer);
+	hc->rh.rh_int_timer.function = etrax_rh_int_timer_do;
+	hc->rh.rh_int_timer.data = (unsigned long)urb;
+	hc->rh.rh_int_timer.expires = jiffies + ((HZ * hc->rh.interval) / 1000);
+	add_timer(&hc->rh.rh_int_timer);
+	
+/*	DBFEXIT; */
+}
+
+static void etrax_rh_int_timer_do(unsigned long ptr)
+{
+	urb_t *urb;
+	etrax_hc_t *hc;
+	
+/*	DBFENTER; */
+	
+	urb = (urb_t*)ptr;
+	hc = urb->dev->bus->hcpriv;
+	
+	if (hc->rh.send) {
+		etrax_rh_send_irq(urb);
+	}
+	
+	etrax_rh_init_int_timer(urb);
+	
+/*	DBFEXIT; */
+}
+
+static void etrax_usb_setup_epid(char epid, char devnum, char endpoint, char packsize, char slow)
+{
+	unsigned long flags;
+	
+	DBFENTER;
+
+	save_flags(flags);
+	cli();
+	
+	if (test_bit(epid, (void *)&ep_usage_bitmask)) {
+		warn("Trying to setup used epid %d", epid);
+		DBFEXIT;
+		return;
+	}
+	
+	set_bit(epid, (void *)&ep_usage_bitmask);
+	dbg_ep("Setting up ep_id %d with devnum %d, endpoint %d and max_len %d",
+	       epid, devnum, endpoint, packsize);
+	
+	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
+	nop();
+	*R_USB_EPT_DATA = IO_STATE(R_USB_EPT_DATA, valid, yes) |
+		IO_FIELD(R_USB_EPT_DATA, ep, endpoint) |
+		IO_FIELD(R_USB_EPT_DATA, dev, devnum) |
+		IO_FIELD(R_USB_EPT_DATA, max_len, packsize) |
+		IO_FIELD(R_USB_EPT_DATA, low_speed, slow);
+
+	restore_flags(flags);
+
+	DBFEXIT;
+}
+
+static void etrax_usb_free_epid(char epid)
+{
+	unsigned long flags;
+	
+	DBFENTER;
+
+	if (!test_bit(epid, (void *)&ep_usage_bitmask)) {
+		warn("Trying to free unused epid %d", epid);
+		DBFEXIT;
+		return;
+	}
+
+	save_flags(flags);
+	cli();
+	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
+	nop();
+	while (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold))printk("+");
+	*R_USB_EPT_DATA = 0;
+	clear_bit(epid, (void *)&ep_usage_bitmask);
+	restore_flags(flags);
+	dbg_ep("epid: %d freed", epid);
+	
+	DBFEXIT;
+}
+
+
+static int etrax_usb_lookup_epid(unsigned char devnum, char endpoint, char slow, int maxp)
+{
+	int i;
+	unsigned long flags;
+	__u32 data;
+	
+	DBFENTER;
+
+	save_flags(flags);
+	
+	/* Skip first ep_id since it is reserved when intr. or iso traffic is used */
+	for (i = 0; i < NBR_OF_EP_DESC; i++) {
+		if (test_bit(i, (void *)&ep_usage_bitmask)) {
+			*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, i);
+			nop();
+			data = *R_USB_EPT_DATA;
+			if ((IO_MASK(R_USB_EPT_DATA, valid) & data) &&
+			    (IO_EXTRACT(R_USB_EPT_DATA, dev, data) == devnum) &&
+			    (IO_EXTRACT(R_USB_EPT_DATA, ep, data) == endpoint) &&
+			    (IO_EXTRACT(R_USB_EPT_DATA, low_speed, data) == slow) &&
+			    (IO_EXTRACT(R_USB_EPT_DATA, max_len, data) == maxp)) {
+				dbg_ep("Found ep_id %d for devnum %d, endpoint %d",
+				       i, devnum, endpoint);
+				DBFEXIT;
+				return i;
+			}
+		}
+	}
+
+	restore_flags(flags);
+	
+	dbg_ep("Found no ep_id for devnum %d, endpoint %d",
+	       devnum, endpoint);
+	DBFEXIT;
+	return -1;
+}
+
+static int etrax_usb_allocate_epid(void)
+{
+	int i;
+	
+	DBFENTER;
+
+	for (i = 0; i < NBR_OF_EP_DESC; i++) {
+		if (!test_bit(i, (void *)&ep_usage_bitmask)) {
+			dbg_ep("Found free ep_id at %d", i);
+			DBFEXIT;
+			return i;
+		}
+	}
+
+	dbg_ep("Found no free ep_id's");
+	DBFEXIT;
+	return -1;
+}
+
+static int etrax_usb_submit_bulk_urb(urb_t *urb)
+{
+	char epid;
+	char devnum;
+	char endpoint;
+	char maxlen;
+	char slow;
+
+	urb_t *tmp_urb;
+	
+	etrax_urb_priv_t *urb_priv;
+	unsigned long flags;
+	
+	DBFENTER;
+
+	devnum = usb_pipedevice(urb->pipe);
+	endpoint = usb_pipeendpoint(urb->pipe);
+	maxlen = usb_maxpacket(urb->dev, urb->pipe,
+			       usb_pipeout(urb->pipe));
+	slow = usb_pipeslow(urb->pipe);
+	
+	epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
+	if (epid == -1) {
+		epid = etrax_usb_allocate_epid();
+		if (epid == -1) {
+			/* We're out of endpoints, return some error */
+			err("We're out of endpoints");
+			return -ENOMEM;
+		}
+		/* Now we have to fill in this ep */
+		etrax_usb_setup_epid(epid, devnum, endpoint, maxlen, slow);
+	}
+	/* Ok, now we got valid endpoint, lets insert some traffic */
+
+	urb->status = -EINPROGRESS;
+
+	save_flags(flags);
+	cli();
+	
+	if (URB_List[epid]) {
+		/* Find end of list and add */
+		for (tmp_urb = URB_List[epid]; tmp_urb->next; tmp_urb = tmp_urb->next)
+			dump_urb(tmp_urb);
+
+		tmp_urb->next = urb;
+		restore_flags(flags);
+	} else {
+		/* If this is the first URB, add the URB and do HW add */
+		URB_List[epid] = urb;
+		restore_flags(flags);
+		etrax_usb_do_bulk_hw_add(urb, epid, maxlen);
+	}
+
+	DBFEXIT;
+
+	return 0;
+}
+
+static int etrax_usb_do_bulk_hw_add(urb_t *urb, char epid, char maxlen)
+{
+	USB_SB_Desc_t *sb_desc_1;
+
+	etrax_urb_priv_t *urb_priv;
+
+	unsigned long flags;
+	__u32 r_usb_ept_data;
+
+	DBFENTER;
+
+	urb_priv = kmalloc(sizeof(etrax_urb_priv_t), GFP_KERNEL);
+	sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+
+	if (usb_pipeout(urb->pipe)) {
+
+		dbg_bulk("Bulk transfer for epid %d is OUT", epid);
+		dbg_bulk("transfer_buffer_length == %d", urb->transfer_buffer_length);
+		dbg_bulk("actual_length == %d", urb->actual_length);
+	
+		if (urb->transfer_buffer_length > 0xffff) {
+			panic(__FILE__ __FUNCTION__ ":urb->transfer_buffer_length > 0xffff\n");
+		}
+
+		sb_desc_1->sw_len = urb->transfer_buffer_length;  /* was actual_length */
+		sb_desc_1->command = IO_FIELD(USB_SB_command, rem, 0) |
+			IO_STATE(USB_SB_command, tt, out) |
+
+#if 0
+			IO_STATE(USB_SB_command, full, no) |
+#else
+			IO_STATE(USB_SB_command, full, yes) |
+#endif
+
+			IO_STATE(USB_SB_command, eot, yes) |
+			IO_STATE(USB_SB_command, eol, yes);
+		
+		dbg_bulk("transfer_buffer is at 0x%08X", urb->transfer_buffer);
+		
+		sb_desc_1->buf = virt_to_phys(urb->transfer_buffer);
+		sb_desc_1->next = 0;
+		
+	} else if (usb_pipein(urb->pipe)) {
+
+		dbg_bulk("Transfer for epid %d is IN", epid);
+		dbg_bulk("transfer_buffer_length = %d", urb->transfer_buffer_length);
+		dbg_bulk("rem is calculated to %d", urb->transfer_buffer_length % maxlen);
+		
+		sb_desc_1->sw_len = urb->transfer_buffer_length ?
+			(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
+		dbg_bulk("sw_len got %d", sb_desc_1->sw_len);
+		dbg_bulk("transfer_buffer is at 0x%08X", urb->transfer_buffer);
+		
+		sb_desc_1->command =
+			IO_FIELD(USB_SB_command, rem,
+				 urb->transfer_buffer_length % maxlen) |
+			IO_STATE(USB_SB_command, tt, in) |
+			IO_STATE(USB_SB_command, eot, yes) |
+			IO_STATE(USB_SB_command, eol, yes);
+		
+		sb_desc_1->buf = 0;
+		sb_desc_1->next = 0;
+
+		urb_priv->rx_offset = 0;
+		urb_priv->eot = 0;
+	}
+	
+	urb_priv->first_sb = sb_desc_1;
+	
+	urb->hcpriv = (void *)urb_priv;
+	
+	/* Reset toggle bits and reset error count, remeber to di and ei */
+	/* Warning: it is possible that this locking doesn't work with bottom-halves */
+
+	save_flags(flags);
+	cli();
+
+	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();
+	if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {
+		panic("Hold was set in %s\n", __FUNCTION__);
+	}
+
+	*R_USB_EPT_DATA &=
+		~(IO_MASK(R_USB_EPT_DATA, error_count_in) |
+		  IO_MASK(R_USB_EPT_DATA, error_count_out));
+	
+	if (usb_pipeout(urb->pipe)) {
+		char toggle =
+		usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
+		*R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_out);
+		*R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_out, toggle);
+	} else {
+		char toggle =
+		usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
+		*R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_in);
+		*R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_in, toggle);
+	}
+		
+	/* Enable the EP descr. */
+
+	set_bit(epid, (void *)&ep_really_active);
+	
+	TxBulkEPList[epid].sub = virt_to_phys(sb_desc_1);
+	TxBulkEPList[epid].hw_len = 0;
+	TxBulkEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
+
+	restore_flags(flags);
+
+	if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) {
+		*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);
+		
+	}
+
+	DBFEXIT;
+}
+
+static int handle_bulk_transfer_attn(char epid, int status)
+{
+	urb_t *old_urb;
+	etrax_urb_priv_t *hc_priv;
+	unsigned long flags;
+
+	DBFENTER;
+
+	clear_bit(epid, (void *)&ep_really_active);
+	
+	old_urb = URB_List[epid];
+	URB_List[epid] = old_urb->next;
+
+	/* if (status == 0 && IN) find data and copy to urb */
+	if (status == 0 && usb_pipein(old_urb->pipe)) {
+		etrax_urb_priv_t *urb_priv;
+		
+		urb_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
+		save_flags(flags);
+		cli();
+		if (urb_priv->eot == 1) {
+			old_urb->actual_length = urb_priv->rx_offset;
+		} else {
+			if (urb_priv->rx_offset == 0) {
+				status = 0;
+			} else {
+				status = -EPROTO;
+			}
+			
+			old_urb->actual_length = 0;
+			err("(BULK) No eot set in IN data!!! rx_offset is: %d", urb_priv->rx_offset);
+		}
+		
+		restore_flags(flags);
+	}
+
+	save_flags(flags);
+	cli();
+		
+	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();
+	if (usb_pipeout(old_urb->pipe)) {
+		char toggle =
+		IO_EXTRACT(R_USB_EPT_DATA, t_out, *R_USB_EPT_DATA);
+		usb_settoggle(old_urb->dev, usb_pipeendpoint(old_urb->pipe),
+			      usb_pipeout(old_urb->pipe), toggle);
+	} else {
+		char toggle =
+		IO_EXTRACT(R_USB_EPT_DATA, t_in, *R_USB_EPT_DATA);
+		usb_settoggle(old_urb->dev, usb_pipeendpoint(old_urb->pipe),
+			      usb_pipeout(old_urb->pipe), toggle);
+	}
+	restore_flags(flags);
+	
+	/* If there are any more URB's in the list we'd better start sending */
+	if (URB_List[epid]) {
+		etrax_usb_do_bulk_hw_add(URB_List[epid], epid,
+					 usb_maxpacket(URB_List[epid]->dev, URB_List[epid]->pipe,
+						       usb_pipeout(URB_List[epid]->pipe)));
+	}
+#if 1
+	else {
+		/* This means that this EP is now free, deconfigure it */
+		etrax_usb_free_epid(epid);
+	}
+#endif
+	
+	/* Remember to free the SB's */
+	hc_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
+	cleanup_sb(hc_priv->first_sb);
+	kfree(hc_priv);
+
+	old_urb->status = status;
+	if (old_urb->complete) {
+		old_urb->complete(old_urb);
+	}
+
+	DBFEXIT;
+}
+
+/* ---------------------------------------------------------------------------- */
+
+static int etrax_usb_submit_ctrl_urb(urb_t *urb)
+{
+	char epid;
+	char devnum;
+	char endpoint;
+	char maxlen;
+	char slow;
+
+	urb_t *tmp_urb;
+	
+	etrax_urb_priv_t *urb_priv;
+	unsigned long flags;
+	
+	DBFENTER;
+
+	devnum = usb_pipedevice(urb->pipe);
+	endpoint = usb_pipeendpoint(urb->pipe);
+	maxlen = usb_maxpacket(urb->dev, urb->pipe,
+			       usb_pipeout(urb->pipe));
+	slow = usb_pipeslow(urb->pipe);
+	
+	epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
+	if (epid == -1) {
+		epid = etrax_usb_allocate_epid();
+		if (epid == -1) {
+			/* We're out of endpoints, return some error */
+			err("We're out of endpoints");
+			return -ENOMEM;
+		}
+		/* Now we have to fill in this ep */
+		etrax_usb_setup_epid(epid, devnum, endpoint, maxlen, slow);
+	}
+	/* Ok, now we got valid endpoint, lets insert some traffic */
+
+	urb->status = -EINPROGRESS;
+
+	save_flags(flags);
+	cli();
+	
+	if (URB_List[epid]) {
+		/* Find end of list and add */
+		for (tmp_urb = URB_List[epid]; tmp_urb->next; tmp_urb = tmp_urb->next)
+			dump_urb(tmp_urb);
+
+		tmp_urb->next = urb;
+		restore_flags(flags);
+	} else {
+		/* If this is the first URB, add the URB and do HW add */
+		URB_List[epid] = urb;
+		restore_flags(flags);
+		etrax_usb_do_ctrl_hw_add(urb, epid, maxlen);
+	}
+
+	DBFEXIT;
+
+	return 0;
+}
+
+static int etrax_usb_do_ctrl_hw_add(urb_t *urb, char epid, char maxlen)
+{
+	USB_SB_Desc_t *sb_desc_1;
+	USB_SB_Desc_t *sb_desc_2;
+	USB_SB_Desc_t *sb_desc_3;
+
+	etrax_urb_priv_t *urb_priv;
+
+	unsigned long flags;
+	__u32 r_usb_ept_data;
+	
+
+	DBFENTER;
+
+	urb_priv = kmalloc(sizeof(etrax_urb_priv_t), GFP_KERNEL);
+	sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+	sb_desc_2 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+
+	if (!(sb_desc_1 && sb_desc_2)) {
+		panic("kmem_cache_alloc in ctrl_hw_add gave NULL pointers !!!\n");
+	}
+	
+	sb_desc_1->sw_len = 8;
+	sb_desc_1->command = IO_FIELD(USB_SB_command, rem, 0) |
+		IO_STATE(USB_SB_command, tt, setup) |
+		IO_STATE(USB_SB_command, full, yes) |
+		IO_STATE(USB_SB_command, eot, yes);
+	
+	sb_desc_1->buf = virt_to_phys(urb->setup_packet);
+	sb_desc_1->next = virt_to_phys(sb_desc_2);
+	dump_sb_desc(sb_desc_1);
+
+	if (usb_pipeout(urb->pipe)) {
+		dbg_ctrl("Transfer for epid %d is OUT", epid);
+
+		/* If this Control OUT transfer has an optional data stage we add an OUT token
+		   before the mandatory IN (status) token, hence the reordered SB list */
+		
+		if (urb->transfer_buffer) {
+			dbg_ctrl("This OUT transfer has an extra data stage");
+			sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+
+			sb_desc_1->next = virt_to_phys(sb_desc_3);
+			
+			sb_desc_3->sw_len = urb->transfer_buffer_length;
+			sb_desc_3->command = IO_STATE(USB_SB_command, tt, out) |
+				IO_STATE(USB_SB_command, full, yes) |
+				IO_STATE(USB_SB_command, eot, yes);
+			sb_desc_3->buf = virt_to_phys(urb->transfer_buffer);
+			sb_desc_3->next = virt_to_phys(sb_desc_2);
+		}
+		
+		sb_desc_2->sw_len = 1;
+		sb_desc_2->command = IO_FIELD(USB_SB_command, rem, 0) |
+			IO_STATE(USB_SB_command, tt, in) |
+			IO_STATE(USB_SB_command, eot, yes) |
+			IO_STATE(USB_SB_command, eol, yes);
+
+		sb_desc_2->buf = 0;
+		sb_desc_2->next = 0;
+		dump_sb_desc(sb_desc_2);
+		
+	} else if (usb_pipein(urb->pipe)) {
+
+		dbg_ctrl("Transfer for epid %d is IN", epid);
+		dbg_ctrl("transfer_buffer_length = %d", urb->transfer_buffer_length);
+		dbg_ctrl("rem is calculated to %d", urb->transfer_buffer_length % maxlen);
+
+		sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);
+		
+		sb_desc_2->sw_len = urb->transfer_buffer_length ?
+			(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
+		dbg_ctrl("sw_len got %d", sb_desc_2->sw_len);
+		
+		sb_desc_2->command =
+			IO_FIELD(USB_SB_command, rem,
+				 urb->transfer_buffer_length % maxlen) |
+			IO_STATE(USB_SB_command, tt, in) |
+			IO_STATE(USB_SB_command, eot, yes);
+		
+		sb_desc_2->buf = 0;
+		sb_desc_2->next = virt_to_phys(sb_desc_3);
+		dump_sb_desc(sb_desc_2);
+
+		sb_desc_3->sw_len = 1;
+		sb_desc_3->command = IO_FIELD(USB_SB_command, rem, 0) |
+			IO_STATE(USB_SB_command, tt, zout) |
+			IO_STATE(USB_SB_command, full, yes) |
+			IO_STATE(USB_SB_command, eot, yes) |
+			IO_STATE(USB_SB_command, eol, yes);
+				
+		sb_desc_3->buf = 0;
+		sb_desc_3->next = 0;
+		dump_sb_desc(sb_desc_3);
+
+		urb_priv->rx_offset = 0;
+		urb_priv->eot = 0;
+	}
+	
+	urb_priv->first_sb = sb_desc_1;
+	
+	urb->hcpriv = (void *)urb_priv;
+	
+	/* Reset toggle bits and reset error count, remeber to di and ei */
+	/* Warning: it is possible that this locking doesn't work with bottom-halves */
+
+	save_flags(flags);
+	cli();
+
+	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();
+	if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {
+		panic("Hold was set in %s\n", __FUNCTION__);
+	}
+	
+
+	*R_USB_EPT_DATA &=
+		~(IO_MASK(R_USB_EPT_DATA, error_count_in) |
+		  IO_MASK(R_USB_EPT_DATA, error_count_out) |
+		  IO_MASK(R_USB_EPT_DATA, t_in) |
+		  IO_MASK(R_USB_EPT_DATA, t_out));
+
+	/* Enable the EP descr. */
+
+	set_bit(epid, (void *)&ep_really_active);
+	
+	TxCtrlEPList[epid].sub = virt_to_phys(sb_desc_1);
+	TxCtrlEPList[epid].hw_len = 0;
+	TxCtrlEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
+	restore_flags(flags);
+
+	dump_ep_desc(&TxCtrlEPList[epid]);
+
+	if (!(*R_DMA_CH8_SUB1_CMD & IO_MASK(R_DMA_CH8_SUB1_CMD, cmd))) {
+		*R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);
+		
+	}
+	
+	DBFEXIT;
+}
+
+static int etrax_usb_submit_urb(urb_t *urb)
+{
+	etrax_hc_t *hc;
+	int rval = -EINVAL;
+	
+	DBFENTER;
+
+	dump_urb(urb);
+	submit_urb_count++;
+	
+	hc = (etrax_hc_t*) urb->dev->bus->hcpriv;
+	
+	if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {
+		/* This request if for the Virtual Root Hub */
+		rval = etrax_rh_submit_urb(urb);
+		
+	} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
+		rval = etrax_usb_submit_ctrl_urb(urb);
+
+	} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
+		rval = etrax_usb_submit_bulk_urb(urb);
+
+	} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+		int bustime;
+
+		if (urb->bandwidth == 0) {
+			bustime = usb_check_bandwidth(urb->dev, urb);
+			if (bustime < 0) {
+				rval = bustime;
+			} else {
+				usb_claim_bandwidth(urb->dev, urb, bustime, 0);
+				rval = etrax_usb_submit_intr_urb(urb);
+			}
+			
+		}
+	} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+		warn("Isochronous traffic is not supported !!!");
+		rval = -EINVAL;
+	}
+
+	DBFEXIT;
+
+	return rval;
+}
+
+static int etrax_usb_unlink_urb(urb_t *urb)
+{
+	etrax_hc_t *hc = urb->dev->bus->hcpriv;
+	int epid;
+	int pos;
+	int devnum, endpoint, slow, maxlen;
+	etrax_urb_priv_t *hc_priv;
+	unsigned long flags;
+	
+	DBFENTER;
+	dump_urb(urb);
+	devnum = usb_pipedevice(urb->pipe);
+	endpoint = usb_pipeendpoint(urb->pipe);
+	slow = usb_pipeslow(urb->pipe);
+	maxlen = usb_maxpacket(urb->dev, urb->pipe,
+			       usb_pipeout(urb->pipe));
+
+	epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen);
+
+	if (epid == -1)
+		return 0;
+	
+	
+	if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {
+		int ret;
+		ret =  etrax_rh_unlink_urb(urb);
+		DBFEXIT;
+		return ret;
+	} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
+		int ret;
+		ret = etrax_usb_unlink_intr_urb(urb);
+		urb->status = -ENOENT;
+		if (urb->complete) {
+			urb->complete(urb);
+		}
+		DBFEXIT;
+		return ret;
+	}
+
+	info("Unlink of BULK or CTRL");
+
+	save_flags(flags);
+	cli();
+	
+	for (epid = 0; epid < 32; epid++) {
+		urb_t *u = URB_List[epid];
+		pos = 0;
+
+		for (; u; u = u->next) {
+			pos++;
+			if (u == urb) {
+				info("Found urb at epid %d, pos %d", epid, pos);
+
+				if (pos == 1) {
+					if (usb_pipetype(u->pipe) == PIPE_CONTROL) {
+						if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
+							/* The EP was enabled, disable it and wait */
+							TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
+							while (*R_DMA_CH8_SUB1_EP == virt_to_phys(&TxCtrlEPList[epid]));
+						}
+						
+					} else if (usb_pipetype(u->pipe) == PIPE_BULK) {
+						if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
+							TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
+							while (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[epid]));
+						}
+					}
+
+					URB_List[epid] = u->next;
+				
+				} else {
+					urb_t *up;
+					for (up = URB_List[epid]; up->next != u; up = up->next);
+					up->next = u->next;
+				}
+				u->status = -ENOENT;
+				if (u->complete) {
+					u->complete(u);
+				}
+				
+				hc_priv = (etrax_urb_priv_t *)u->hcpriv;
+				cleanup_sb(hc_priv->first_sb);
+				kfree(hc_priv);
+			}
+		}
+	}
+
+	restore_flags(flags);
+		
+	DBFEXIT;
+	return 0;
+}
+
+static int etrax_usb_get_frame_number(struct usb_device *usb_dev)
+{
+	DBFENTER;
+	DBFEXIT;
+	return (*R_USB_FM_NUMBER);
+}
+
+static int etrax_usb_allocate_dev(struct usb_device *usb_dev)
+{  
+	DBFENTER;
+	DBFEXIT;
+	return 0;
+}
+
+static int etrax_usb_deallocate_dev(struct usb_device *usb_dev)
+{
+	DBFENTER;
+	DBFEXIT;
+	return 0;
+}
+
+static void etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs)
+{
+	etrax_hc_t *hc = (etrax_hc_t *)vhc;
+	int epid;
+	char eol;
+	urb_t *urb;
+	USB_EP_Desc_t *tmp_ep;
+	USB_SB_Desc_t *tmp_sb;
+	
+	DBFENTER;
+
+	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub0_descr)) {
+		info("dma8_sub0_descr (BULK) intr.");
+		*R_DMA_CH8_SUB0_CLR_INTR = IO_STATE(R_DMA_CH8_SUB0_CLR_INTR, clr_descr, do);
+	}
+	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub1_descr)) {
+		info("dma8_sub1_descr (CTRL) intr.");
+		*R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do);
+	}
+	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) {
+		info("dma8_sub2_descr (INT) intr.");
+		*R_DMA_CH8_SUB2_CLR_INTR = IO_STATE(R_DMA_CH8_SUB2_CLR_INTR, clr_descr, do);
+	}
+	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub3_descr)) {
+		info("dma8_sub3_descr (ISO) intr.");
+		*R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do);
+	}
+	
+	DBFEXIT;
+}
+
+static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs)
+{
+	int epid = 0;
+	urb_t *urb;
+	etrax_urb_priv_t *urb_priv;
+		
+	*R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do);
+
+	while (myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) {
+		if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) {
+
+			goto skip_out;
+		}
+
+		if (myNextRxDesc->status & IO_MASK(USB_IN_status, error)) {
+			
+			goto skip_out;
+		}
+		
+		epid = IO_EXTRACT(USB_IN_status, epid, myNextRxDesc->status);
+
+		urb = URB_List[epid];
+
+		if (urb && usb_pipein(urb->pipe)) {
+			urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
+
+			if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+				struct in_chunk *in;
+				dbg_intr("Packet for epid %d in rx buffers", epid);
+				in = kmalloc(sizeof(struct in_chunk), GFP_ATOMIC);
+				in->length = myNextRxDesc->hw_len;
+				in->data = kmalloc(in->length, GFP_ATOMIC);
+				memcpy(in->data, phys_to_virt(myNextRxDesc->buf), in->length);
+				list_add_tail(&in->list, &urb_priv->ep_in_list);
+#ifndef ETRAX_USB_INTR_IRQ
+				etrax_usb_hc_intr_top_half(irq, vhc, regs);
+#endif
+				
+			} else {
+				if ((urb_priv->rx_offset + myNextRxDesc->hw_len) >
+				    urb->transfer_buffer_length) {
+					err("Packet (epid: %d) in RX buffer was bigger "
+					    "than the URB has room for !!!", epid);
+					goto skip_out;
+				}
+				
+				memcpy(urb->transfer_buffer + urb_priv->rx_offset,
+				       phys_to_virt(myNextRxDesc->buf), myNextRxDesc->hw_len);
+				
+				urb_priv->rx_offset += myNextRxDesc->hw_len;
+			}
+			
+			if (myNextRxDesc->status & IO_MASK(USB_IN_status, eot)) {
+				urb_priv->eot = 1;
+			}
+			
+		} else {
+			err("This is almost fatal, inpacket for epid %d which does not exist "
+			    " or is out !!!\nURB was at 0x%08X", epid, urb);
+			
+			goto skip_out;
+		}
+
+	skip_out:
+		myPrevRxDesc = myNextRxDesc;
+		myPrevRxDesc->command |= IO_MASK(USB_IN_command, eol);
+		myLastRxDesc->command &= ~IO_MASK(USB_IN_command, eol);
+		myLastRxDesc = myPrevRxDesc;
+
+		myNextRxDesc->status = 0;
+		myNextRxDesc = phys_to_virt(myNextRxDesc->next);
+	}
+}
+
+
+
+static void cleanup_sb(USB_SB_Desc_t *sb)
+{
+	USB_SB_Desc_t *next_sb;
+	
+	DBFENTER;
+
+	if (sb == NULL) {
+		err("cleanup_sb was given a NULL pointer");
+		return;
+	}
+
+	while (!(sb->command & IO_MASK(USB_SB_command, eol))) {
+		next_sb = (USB_SB_Desc_t *)phys_to_virt(sb->next);
+		kmem_cache_free(usb_desc_cache, sb);
+		sb = next_sb;
+	}
+
+	kmem_cache_free(usb_desc_cache, sb);
+
+	DBFEXIT;
+
+}
+
+static int handle_control_transfer_attn(char epid, int status)
+{
+	urb_t *old_urb;
+	etrax_urb_priv_t *hc_priv;	
+
+	DBFENTER;
+
+	clear_bit(epid, (void *)&ep_really_active);
+	
+	old_urb = URB_List[epid];
+	URB_List[epid] = old_urb->next;
+	
+	/* if (status == 0 && IN) find data and copy to urb */
+	if (status == 0 && usb_pipein(old_urb->pipe)) {
+		unsigned long flags;
+		etrax_urb_priv_t *urb_priv;
+
+		urb_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
+		save_flags(flags);
+		cli();
+		if (urb_priv->eot == 1) {
+			old_urb->actual_length = urb_priv->rx_offset;
+			dbg_ctrl("urb_priv->rx_offset: %d in handle_control_attn", urb_priv->rx_offset);
+		} else {
+			status = -EPROTO;
+			old_urb->actual_length = 0;
+			err("(CTRL) No eot set in IN data!!! rx_offset: %d", urb_priv->rx_offset);
+		}
+
+		restore_flags(flags);
+	}
+	
+	/* If there are any more URB's in the list we'd better start sending */
+	if (URB_List[epid]) {
+		etrax_usb_do_ctrl_hw_add(URB_List[epid], epid,
+					 usb_maxpacket(URB_List[epid]->dev, URB_List[epid]->pipe,
+						       usb_pipeout(URB_List[epid]->pipe)));
+	}
+#if 1
+	else {
+		/* This means that this EP is now free, deconfigure it */
+		etrax_usb_free_epid(epid);
+	}
+#endif
+	
+	/* Remember to free the SB's */
+	hc_priv = (etrax_urb_priv_t *)old_urb->hcpriv;
+	cleanup_sb(hc_priv->first_sb);
+	kfree(hc_priv);
+
+	old_urb->status = status;
+	if (old_urb->complete) {
+		old_urb->complete(old_urb);
+	}
+
+	DBFEXIT;
+}
+
+
+
+static void etrax_usb_hc_intr_bottom_half(void *data)
+{
+	struct usb_reg_context *reg = (struct usb_reg_context *)data;
+	urb_t *old_urb;
+	
+	int error_code;
+	int epid;
+
+	__u32 r_usb_ept_data;
+
+	etrax_hc_t *hc = reg->hc; 
+	__u16 r_usb_rh_port_status_1;
+	__u16 r_usb_rh_port_status_2;
+	
+	DBFENTER;
+
+	if (reg->r_usb_irq_mask_read & IO_MASK(R_USB_IRQ_MASK_READ, port_status)) {
+
+		/*
+		  The Etrax RH does not include a wPortChange register, so this has
+		  to be handled in software. See section 11.16.2.6.2 in USB 1.1 spec
+		  for details.
+		*/
+		
+		r_usb_rh_port_status_1 = reg->r_usb_rh_port_status_1;
+		r_usb_rh_port_status_2 = reg->r_usb_rh_port_status_2;
+		
+		dbg_rh("port_status pending");
+		dbg_rh("r_usb_rh_port_status_1: 0x%04X", r_usb_rh_port_status_1);
+		dbg_rh("r_usb_rh_port_status_2: 0x%04X", r_usb_rh_port_status_2);
+
+		/* C_PORT_CONNECTION is set on any transition */
+		hc->rh.wPortChange_1 |=
+			((r_usb_rh_port_status_1 & (1 << RH_PORT_CONNECTION)) !=
+			 (hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_CONNECTION))) ?
+			(1 << RH_PORT_CONNECTION) : 0;
+		
+		hc->rh.wPortChange_2 |=
+			((r_usb_rh_port_status_2 & (1 << RH_PORT_CONNECTION)) !=
+			 (hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_CONNECTION))) ?
+			(1 << RH_PORT_CONNECTION) : 0;
+
+		/* C_PORT_ENABLE is _only_ set on a one to zero transition */
+		hc->rh.wPortChange_1 |=
+			((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_ENABLE))
+			 && !(r_usb_rh_port_status_1 & (1 << RH_PORT_ENABLE))) ?
+			(1 << RH_PORT_ENABLE) : 0;
+		
+		hc->rh.wPortChange_2 |=
+			((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_ENABLE))
+			 && !(r_usb_rh_port_status_2 & (1 << RH_PORT_ENABLE))) ?
+			(1 << RH_PORT_ENABLE) : 0;
+		
+		/* C_PORT_SUSPEND seems difficult, lets ignore it.. (for now) */
+		
+		/* C_PORT_RESET is _only_ set on a transition from the resetting state
+		   to the enabled state */
+		hc->rh.wPortChange_1 |=
+			((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_RESET))
+			 && (r_usb_rh_port_status_1 & (1 << RH_PORT_ENABLE))) ?
+			(1 << RH_PORT_RESET) : 0;
+		
+		hc->rh.wPortChange_2 |=
+			((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_RESET))
+			 && (r_usb_rh_port_status_2 & (1 << RH_PORT_ENABLE))) ?
+			(1 << RH_PORT_RESET) : 0;
+		
+		hc->rh.prev_wPortStatus_1 = r_usb_rh_port_status_1;
+		hc->rh.prev_wPortStatus_2 = r_usb_rh_port_status_2;	
+	}
+
+	for (epid = 0; epid < 32; epid++) {
+
+		unsigned long flags;
+
+		save_flags(flags);
+		cli();
+		*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();
+		r_usb_ept_data = *R_USB_EPT_DATA;
+		restore_flags(flags);
+
+		if (r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, hold)) {
+			warn("Was hold for epid %d", epid);
+			continue;
+		}
+
+		if (!(r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, valid))) {
+			continue;
+		}
+		
+		
+		if (test_bit(epid, (void *)&reg->r_usb_epid_attn)) {
+
+			if (URB_List[epid] == NULL) {
+				err("R_USB_EPT_DATA is 0x%08X", r_usb_ept_data);
+				err("submit urb has been called %d times..", submit_urb_count);
+				err("EPID_ATTN for epid %d, with NULL entry in list", epid);
+				return;
+			}
+			
+			dbg_ep("r_usb_ept_data [%d] == 0x%08X", epid,
+			       r_usb_ept_data);
+			
+			error_code = IO_EXTRACT(R_USB_EPT_DATA, error_code,
+						r_usb_ept_data);
+			
+			if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
+				/* no_error means that this urb was successfully sent or that we have
+				   some undefinde error*/
+				
+				if (IO_EXTRACT(R_USB_EPT_DATA, error_count_out, r_usb_ept_data) == 3 ||
+				    IO_EXTRACT(R_USB_EPT_DATA, error_count_in, r_usb_ept_data) == 3) {
+				/* Actually there were transmission errors */
+					warn("Undefined error for endpoint %d", epid);
+					if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {
+						handle_control_transfer_attn(epid, -EPROTO);
+					} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {
+						handle_bulk_transfer_attn(epid, -EPROTO);
+					} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
+						handle_intr_transfer_attn(epid, -EPROTO);
+					}
+							   
+				} else {
+
+					if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {
+						if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
+							etrax_usb_do_intr_recover(epid);
+						} else {
+							panic("Epid attention for epid %d (none INTR), with no errors and no "
+							      "exessive retry r_usb_status is 0x%02X\n",
+							      epid, reg->r_usb_status);
+						}
+						
+					} else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {
+						panic("Epid attention for epid %d, with no errors and no "
+						      "exessive retry r_usb_status is 0x%02X\n",
+						      epid, reg->r_usb_status);
+						
+					}
+					
+					warn("Epid attention for epid %d, with no errors and no "
+					     "exessive retry r_usb_status is 0x%02X",
+					     epid, reg->r_usb_status);
+					warn("OUT error count: %d", IO_EXTRACT(R_USB_EPT_DATA, error_count_out,
+									       r_usb_ept_data));
+					warn("IN  error count: %d", IO_EXTRACT(R_USB_EPT_DATA, error_count_in,
+									       r_usb_ept_data));
+					
+
+				}
+				
+			} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, stall)) {
+				warn("Stall for endpoint %d", epid);
+				if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {
+					handle_control_transfer_attn(epid, -EPIPE);
+				} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {
+					handle_bulk_transfer_attn(epid, -EPIPE);
+				} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
+					handle_intr_transfer_attn(epid, -EPIPE);
+				}
+				
+				
+			} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, bus_error)) {
+				panic("USB bus error for endpoint %d\n", epid);
+				
+			} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, buffer_error)) {
+				warn("Buffer error for endpoint %d", epid);
+
+				if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {
+					handle_control_transfer_attn(epid, -EPROTO);
+				} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {
+					handle_bulk_transfer_attn(epid, -EPROTO);
+				} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
+					handle_intr_transfer_attn(epid, -EPROTO);
+				}
+
+			}
+		} else if (test_bit(epid, (void *)&ep_really_active)) {
+			/* Should really be else if (testbit(really active)) */
+
+			if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {
+
+				if (!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable))) {
+					/* Now we have to verify that this CTRL endpoint got disabled
+					   cause it reached end of list with no error */
+					
+					if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) ==
+					    IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
+						/*
+						  This means that the endpoint has no error, is disabled
+						  and had inserted traffic,
+						  i.e. transfer successfully completed
+						*/
+						dbg_ctrl("Last SB for CTRL %d sent successfully", epid);
+						handle_control_transfer_attn(epid, 0);
+					}
+				}
+				
+			} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {
+				if (!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable))) {
+					/* Now we have to verify that this BULK endpoint go disabled
+					   cause it reached end of list with no error */
+
+					if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) ==
+					    IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
+						/*
+						  This means that the endpoint has no error, is disabled
+						  and had inserted traffic,
+						  i.e. transfer successfully completed
+						*/
+						dbg_bulk("Last SB for BULK %d sent successfully", epid);
+						handle_bulk_transfer_attn(epid, 0);
+					}
+				}
+			} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {
+				handle_intr_transfer_attn(epid, 0);
+			}
+		}
+		
+	}	
+
+	kfree(reg);
+
+	DBFEXIT;
+}
+
+
+static void etrax_usb_hc_intr_top_half(int irq, void *vhc, struct pt_regs *regs)
+{
+	struct usb_reg_context *reg;
+
+	DBFENTER;
+
+	reg = (struct usb_reg_context *)kmalloc(sizeof(struct usb_reg_context), GFP_ATOMIC);
+
+	if (!(reg)) {
+		panic("kmalloc failed in top_half\n");
+	}
+
+	reg->hc = (etrax_hc_t *)vhc;
+	reg->r_usb_irq_mask_read    = *R_USB_IRQ_MASK_READ;
+	reg->r_usb_status           = *R_USB_STATUS;
+
+#if 0
+	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {
+		panic("r_usb_status said perror\n");
+	}
+	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {
+		panic("r_usb_status said ourun !!!\n");
+	}
+#endif
+	
+	reg->r_usb_epid_attn        = *R_USB_EPID_ATTN;
+
+	reg->r_usb_rh_port_status_1 = *R_USB_RH_PORT_STATUS_1;
+	reg->r_usb_rh_port_status_2 = *R_USB_RH_PORT_STATUS_2;
+
+	reg->usb_bh.sync = 0;
+	reg->usb_bh.routine = etrax_usb_hc_intr_bottom_half;
+	reg->usb_bh.data = reg;
+
+	queue_task(&reg->usb_bh, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+
+	DBFEXIT;
+}
+
+static int etrax_rh_submit_urb(urb_t *urb)
+{
+	struct usb_device *usb_dev = urb->dev;
+	etrax_hc_t *hc = usb_dev->bus->hcpriv;
+	unsigned int pipe = urb->pipe;
+	devrequest *cmd = (devrequest *) urb->setup_packet;
+	void *data = urb->transfer_buffer;
+	int leni = urb->transfer_buffer_length;
+	int len = 0;
+	int status = 0;
+	int stat = 0;
+	int i;
+
+	__u16 cstatus;
+
+	__u16 bmRType_bReq;
+	__u16 wValue;
+	__u16 wIndex;
+	__u16 wLength;
+
+	DBFENTER;
+
+	if (usb_pipetype (pipe) == PIPE_INTERRUPT) {
+		dbg_rh("Root-Hub submit IRQ: every %d ms", urb->interval);
+		hc->rh.urb = urb;
+		hc->rh.send = 1;
+		hc->rh.interval = urb->interval;
+		etrax_rh_init_int_timer(urb);
+		DBFEXIT;
+		
+		return 0;
+	}
+
+	bmRType_bReq = cmd->requesttype | cmd->request << 8;
+	wValue = le16_to_cpu(cmd->value);
+	wIndex = le16_to_cpu(cmd->index);
+	wLength = le16_to_cpu(cmd->length);
+
+	dbg_rh("bmRType_bReq : 0x%04X (%d)", bmRType_bReq, bmRType_bReq);
+	dbg_rh("wValue       : 0x%04X (%d)", wValue, wValue);
+	dbg_rh("wIndex       : 0x%04X (%d)", wIndex, wIndex);
+	dbg_rh("wLength      : 0x%04X (%d)", wLength, wLength);
+	
+	switch (bmRType_bReq) {
+		
+		/* Request Destination:
+		   without flags: Device, 
+		   RH_INTERFACE: interface, 
+		   RH_ENDPOINT: endpoint,
+		   RH_CLASS means HUB here, 
+		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
+		 */
+
+	case RH_GET_STATUS:
+		*(__u16 *) data = cpu_to_le16 (1);
+		OK (2);
+		
+	case RH_GET_STATUS | RH_INTERFACE:
+		*(__u16 *) data = cpu_to_le16 (0);
+		OK (2);
+		
+	case RH_GET_STATUS | RH_ENDPOINT:
+		*(__u16 *) data = cpu_to_le16 (0);
+		OK (2);
+		
+	case RH_GET_STATUS | RH_CLASS:
+		*(__u32 *) data = cpu_to_le32 (0);
+		OK (4);		/* hub power ** */
+		
+	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+                if (wIndex == 1) {
+			*((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_1);
+			*((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_1);
+                }
+                else if (wIndex == 2) {
+			*((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_2);
+			*((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_2);
+                }
+                else {
+			dbg_rh("RH_GET_STATUS whith invalid wIndex !!");
+			OK(0);
+                }
+		
+                OK(4);
+                
+	case RH_CLEAR_FEATURE | RH_ENDPOINT:
+		switch (wValue) {
+		case (RH_ENDPOINT_STALL):
+			OK (0);
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_CLASS:
+		switch (wValue) {
+		case (RH_C_HUB_OVER_CURRENT):
+			OK (0);	/* hub power over current ** */
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+		case (RH_PORT_ENABLE):
+			if (wIndex == 1) {
+
+				dbg_rh("trying to do disable of port 1");
+
+				*R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, yes);
+				while (hc->rh.prev_wPortStatus_1 &
+				       IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes));
+				*R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no);
+				dbg_rh("Port 1 is disabled");
+
+			} else if (wIndex == 2) {
+
+				dbg_rh("trying to do disable of port 2");
+				
+				*R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, yes);
+				while (hc->rh.prev_wPortStatus_2 &
+				       IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, yes));
+				*R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no);
+				dbg_rh("Port 2 is disabled");
+
+			} else {
+				dbg_rh("RH_CLEAR_FEATURE->RH_PORT_ENABLE "
+				       "with invalid wIndex == %d!!", wIndex);
+			}			
+				
+			OK (0);
+		case (RH_PORT_SUSPEND):
+			/* Opposite to suspend should be resume, so well do a resume */
+			if (wIndex == 1) {
+				*R_USB_COMMAND =
+					IO_STATE(R_USB_COMMAND, port_sel, port1) |
+					IO_STATE(R_USB_COMMAND, port_cmd, resume)|
+					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
+			} else if (wIndex == 2) {
+				*R_USB_COMMAND =
+					IO_STATE(R_USB_COMMAND, port_sel, port2) |
+					IO_STATE(R_USB_COMMAND, port_cmd, resume)|
+					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
+			} else {
+				dbg_rh("RH_CLEAR_FEATURE->RH_PORT_SUSPEND "
+				       "with invalid wIndex == %d!!", wIndex);
+			}
+			
+			OK (0);
+		case (RH_PORT_POWER):
+			OK (0);	/* port power ** */
+		case (RH_C_PORT_CONNECTION):
+			
+                        if (wIndex == 1) {
+				hc->rh.wPortChange_1 &= ~(1 << RH_PORT_CONNECTION);
+                        }
+                        else if (wIndex == 2) {
+				hc->rh.wPortChange_2 &= ~(1 << RH_PORT_CONNECTION);
+                        }
+                        else {
+				dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_CONNECTION "
+				       "with invalid wIndex == %d!!", wIndex);
+                        }
+
+			OK (0);
+		case (RH_C_PORT_ENABLE):
+			if (wIndex == 1) {
+				hc->rh.wPortChange_1 &= ~(1 << RH_PORT_ENABLE);
+			}
+			else if (wIndex == 2) {
+				hc->rh.wPortChange_2 &= ~(1 << RH_PORT_ENABLE);
+			}
+			else {
+				dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_ENABLE "
+				       "with invalid wIndex == %d!!", wIndex);
+			}
+			OK (0);
+		case (RH_C_PORT_SUSPEND):
+/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
+			OK (0);
+		case (RH_C_PORT_OVER_CURRENT):
+			OK (0);	/* port power over current ** */
+		case (RH_C_PORT_RESET):
+			if (wIndex == 1) {
+				hc->rh.wPortChange_1 &= ~(1 << RH_PORT_RESET);
+			}
+			else if (wIndex == 2) {
+				dbg_rh("This is wPortChange before clear: 0x%04X", hc->rh.wPortChange_2);
+				
+				hc->rh.wPortChange_2 &= ~(1 << RH_PORT_RESET);
+				dbg_rh("This is wPortChange after clear: 0x%04X", hc->rh.wPortChange_2);
+			} else {
+				dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_RESET "
+				       "with invalid index == %d!!", wIndex);
+			}
+
+			OK (0);
+		
+		}
+		break;
+		
+	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+		case (RH_PORT_SUSPEND):
+			if (wIndex == 1) {
+				*R_USB_COMMAND =
+					IO_STATE(R_USB_COMMAND, port_sel, port1) |
+					IO_STATE(R_USB_COMMAND, port_cmd, suspend) |
+					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
+			} else if (wIndex == 2) {
+				*R_USB_COMMAND =
+					IO_STATE(R_USB_COMMAND, port_sel, port2) |
+					IO_STATE(R_USB_COMMAND, port_cmd, suspend) |
+					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);
+			} else {
+				dbg_rh("RH_SET_FEATURE->RH_C_PORT_SUSPEND "
+				       "with invalid wIndex == %d!!", wIndex);
+			}			
+
+			OK (0);
+		case (RH_PORT_RESET):
+                        if (wIndex == 1) {
+				int port1_retry;
+				
+			port1_redo:
+				dbg_rh("Doing reset of port 1");
+
+				*R_USB_COMMAND =
+					IO_STATE(R_USB_COMMAND, port_cmd, reset) |
+					IO_STATE(R_USB_COMMAND, port_sel, port1);
+
+				/* We must once again wait at least 10ms for the device to recover */
+
+				port1_retry = 0;
+				while (!((*((volatile __u16 *)&hc->rh.prev_wPortStatus_1)) &
+					 IO_STATE(R_USB_RH_PORT_STATUS_1,
+						  enabled, yes))) {
+					printk(""); if (port1_retry++ >= 10000) {goto port1_redo;}
+				}
+				
+				/* This only seems to work if we use printk,
+				   not even schedule() works !!! WHY ?? */
+
+				udelay(15000);
+                        }
+                        else if (wIndex == 2) {
+				int port2_retry;
+				
+			port2_redo:
+				dbg_rh("Doing reset of port 2");
+				
+				*R_USB_COMMAND =
+					IO_STATE(R_USB_COMMAND, port_cmd, reset) |
+					IO_STATE(R_USB_COMMAND, port_sel, port2);
+
+				/* We must once again wait at least 10ms for the device to recover */
+
+				port2_retry = 0;
+				while (!((*((volatile __u16 *)&hc->rh.prev_wPortStatus_2)) &
+					 IO_STATE(R_USB_RH_PORT_STATUS_2,
+						  enabled, yes))) {
+					printk(""); if (port2_retry++ >= 10000) {goto port2_redo;}
+				}
+				
+				/* This only seems to work if we use printk,
+				   not even schedule() works !!! WHY ?? */
+
+				udelay(15000);
+                        }
+
+			/* Try to bring the HC into running state */
+			*R_USB_COMMAND =
+				IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);
+			
+			nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
+			
+                        dbg_rh("...Done");
+                        OK(0);
+                        
+		case (RH_PORT_POWER):
+			OK (0);	/* port power ** */
+		case (RH_PORT_ENABLE):
+			/* There is no rh port enable command in the Etrax USB interface!!!! */
+			OK (0);
+                        
+		}
+		break;
+		
+	case RH_SET_ADDRESS:
+		hc->rh.devnum = wValue;
+                dbg_rh("RH address set to: %d", hc->rh.devnum);
+		OK (0);
+		
+	case RH_GET_DESCRIPTOR:
+		switch ((wValue & 0xff00) >> 8) {
+		case (0x01):	/* device descriptor */
+			len = min (leni, min (sizeof (root_hub_dev_des), wLength));
+			memcpy (data, root_hub_dev_des, len);
+			OK (len);
+		case (0x02):	/* configuration descriptor */
+			len = min (leni, min (sizeof (root_hub_config_des), wLength));
+			memcpy (data, root_hub_config_des, len);
+			OK (len);
+		case (0x03):	/* string descriptors */
+			len = usb_root_hub_string (wValue & 0xff,
+						   0xff, "ETRAX 100LX",
+						   data, wLength);
+			if (len > 0) {
+				OK (min (leni, len));
+			} else 
+				stat = -EPIPE;
+		}
+		break;
+		
+	case RH_GET_DESCRIPTOR | RH_CLASS:
+		root_hub_hub_des[2] = hc->rh.numports;
+		len = min (leni, min (sizeof (root_hub_hub_des), wLength));
+		memcpy (data, root_hub_hub_des, len);
+		OK (len);
+		
+	case RH_GET_CONFIGURATION:
+		*(__u8 *) data = 0x01;
+		OK (1);
+		
+	case RH_SET_CONFIGURATION:
+		OK (0);
+		
+	default:
+		stat = -EPIPE;
+	}
+
+	urb->actual_length = len;
+	urb->status = stat;
+	urb->dev=NULL;
+	if (urb->complete) {
+		urb->complete (urb);
+	}
+	DBFEXIT;
+	
+	return 0;
+}
+
+static int __init etrax_usb_hc_init(void)
+{
+	static etrax_hc_t *hc;
+	struct usb_bus *bus;
+	struct usb_device *usb_rh;
+	
+	DBFENTER;
+
+	info("ETRAX 100LX USB-HCD %s (c) 2001 Axis Communications AB\n", usb_hcd_version);
+	
+	hc = kmalloc(sizeof(etrax_hc_t), GFP_KERNEL);
+
+	/* We use kmem_cache_* to make sure that all DMA desc. are dword aligned */
+	usb_desc_cache = kmem_cache_create("usb_desc_cache", sizeof(USB_EP_Desc_t), 0, 0, 0, 0);
+	if (!usb_desc_cache) {
+		panic("USB Desc Cache allocation failed !!!\n");
+	}
+	
+	etrax_usb_bus = bus = usb_alloc_bus(&etrax_usb_device_operations);
+	hc->bus = bus;
+	bus->hcpriv = hc;
+        
+	/* Initalize RH to the default address.
+	   And make sure that we have no status change indication */
+	hc->rh.numports = 2;  /* The RH has two ports */
+	hc->rh.devnum = 0;
+	hc->rh.wPortChange_1 = 0;
+	hc->rh.wPortChange_2 = 0;
+
+	/* Also initate the previous values to zero */
+	hc->rh.prev_wPortStatus_1 = 0;
+	hc->rh.prev_wPortStatus_2 = 0;
+
+	/* Initialize the intr-traffic flags */
+	hc->intr.sleeping = 0;
+	hc->intr.wq = NULL;
+        
+	/* Initially all ep's are free except ep 0 */
+	ep_usage_bitmask = 0;
+	set_bit(0, (void *)&ep_usage_bitmask);
+	ep_really_active = 0;
+
+	memset(URB_List, 0, sizeof(URB_List));
+
+	/* This code should really be moved */
+
+        if (request_dma(8, "ETRAX 100LX built-in USB (Tx)")) {
+		err("Could not allocate DMA ch 8 for USB");
+		etrax_usb_hc_cleanup();
+		DBFEXIT;
+		return -1;
+	}
+	
+	if (request_dma(9, "ETRAX 100LX built-in USB (Rx)")) {
+		err("Could not allocate DMA ch 9 for USB");
+		etrax_usb_hc_cleanup();
+		DBFEXIT;
+		return -1;
+	}	
+#if 0  /* Moved to head.S */        
+	*R_GEN_CONFIG = genconfig_shadow =
+		(genconfig_shadow & ~(IO_MASK(R_GEN_CONFIG, usb1) |
+				      IO_MASK(R_GEN_CONFIG, usb2) |
+				      IO_MASK(R_GEN_CONFIG, dma8) |
+				      IO_MASK(R_GEN_CONFIG, dma9))) |
+		IO_STATE(R_GEN_CONFIG, dma8, usb) |
+		IO_STATE(R_GEN_CONFIG, dma9, usb)
+#ifdef CONFIG_ETRAX_USB_HOST_PORT1
+		| IO_STATE(R_GEN_CONFIG, usb1, select)
+#endif
+#ifdef CONFIG_ETRAX_USB_HOST_PORT2
+		| IO_STATE(R_GEN_CONFIG, usb2, select)
+#endif
+	;
+#endif
+	
+	usb_register_bus(hc->bus);
+
+	/* We may have to set more bits, but these are the obvious ones */
+	*R_IRQ_MASK2_SET =
+		IO_STATE(R_IRQ_MASK2_SET, dma8_sub0_descr, set) |
+		IO_STATE(R_IRQ_MASK2_SET, dma8_sub1_descr, set) |
+		IO_STATE(R_IRQ_MASK2_SET, dma8_sub2_descr, set) |
+		IO_STATE(R_IRQ_MASK2_SET, dma8_sub3_descr, set);
+
+	*R_IRQ_MASK2_SET =
+		IO_STATE(R_IRQ_MASK2_SET, dma9_eop, set) |
+		IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set);
+
+	*R_USB_IRQ_MASK_SET = 
+		IO_STATE(R_USB_IRQ_MASK_SET, ctl_status, set) |
+		IO_STATE(R_USB_IRQ_MASK_SET, ctl_eot, set) |
+		IO_STATE(R_USB_IRQ_MASK_SET, bulk_eot, set) |
+#ifdef ETRAX_USB_INTR_IRQ
+		IO_STATE(R_USB_IRQ_MASK_SET, intr_eot, set) |
+#endif
+		IO_STATE(R_USB_IRQ_MASK_SET, epid_attn, set) |
+		IO_STATE(R_USB_IRQ_MASK_SET, port_status, set);
+	
+	if (request_irq(ETRAX_USB_HC_IRQ, etrax_usb_hc_intr_top_half, 0,
+			"ETRAX 100LX built-in USB (HC)", hc)) {
+		err("Could not allocate IRQ %d for USB", ETRAX_USB_HC_IRQ);
+		etrax_usb_hc_cleanup();
+		DBFEXIT;
+		return -1;
+	}
+	
+	if (request_irq(ETRAX_USB_RX_IRQ, etrax_usb_rx_interrupt, 0,
+			"ETRAX 100LX built-in USB (Rx)", hc)) {
+		err("Could not allocate IRQ %d for USB", ETRAX_USB_RX_IRQ);
+		etrax_usb_hc_cleanup();
+		DBFEXIT;
+		return -1;
+	}
+	
+	if (request_irq(ETRAX_USB_TX_IRQ, etrax_usb_tx_interrupt, 0,
+			"ETRAX 100LX built-in USB (Tx)", hc)) {
+		err("Could not allocate IRQ %d for USB", ETRAX_USB_TX_IRQ);
+		etrax_usb_hc_cleanup();
+		DBFEXIT;
+		return -1;
+	}
+
+	/* Reset the USB interface (configures as HC) */
+	*R_USB_COMMAND =
+		IO_STATE(R_USB_COMMAND, ctrl_cmd, reset) |
+		IO_STATE(R_USB_COMMAND, port_cmd, reset);
+	
+	nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
+#if 1
+	/* Initate PSTART to all unallocatable bit times */
+	*R_USB_FM_PSTART = IO_FIELD(R_USB_FM_PSTART, value, 10000);
+#endif
+
+#ifdef CONFIG_ETRAX_USB_HOST_PORT1
+	*R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no);
+#endif
+	
+#ifdef CONFIG_ETRAX_USB_HOST_PORT2
+	*R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no);
+#endif
+	
+	*R_USB_COMMAND =
+		IO_STATE(R_USB_COMMAND, ctrl_cmd, host_config) |
+		IO_STATE(R_USB_COMMAND, port_cmd, reset);
+	
+	nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
+
+	*R_USB_COMMAND =
+		IO_STATE(R_USB_COMMAND, port_sel, port1) |
+		IO_STATE(R_USB_COMMAND, port_cmd, reset);
+
+	nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
+
+	/* Here we must wait at least 10ms so the device has time to recover */
+	udelay(15000);
+
+	init_rx_buffers();
+	init_tx_bulk_ep();
+	init_tx_ctrl_ep();
+	init_tx_intr_ep();
+
+	/* This works. It seems like the host_run command only has effect when a device is connected,
+	 i.e. it has to be done when a interrup */
+	*R_USB_COMMAND =
+		IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);
+	
+	nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));
+
+	usb_rh = usb_alloc_dev(NULL, hc->bus);
+	hc->bus->root_hub = usb_rh;
+	usb_connect(usb_rh);
+	usb_new_device(usb_rh);
+
+	DBFEXIT;
+	
+	return 0;
+}
+
+static void etrax_usb_hc_cleanup(void)
+{
+	DBFENTER;
+	
+	free_irq(ETRAX_USB_HC_IRQ, NULL);
+	free_irq(ETRAX_USB_RX_IRQ, NULL);
+	free_irq(ETRAX_USB_TX_IRQ, NULL);
+
+	free_dma(8);
+	free_dma(9);
+	usb_deregister_bus(etrax_usb_bus);
+
+	DBFEXIT;
+}
+
+module_init(etrax_usb_hc_init);
+module_exit(etrax_usb_hc_cleanup);
diff -u --recursive --new-file v2.4.3/linux/arch/cris/drivers/usb-host.h linux/arch/cris/drivers/usb-host.h
--- v2.4.3/linux/arch/cris/drivers/usb-host.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/usb-host.h	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,245 @@
+#ifndef __LINUX_ETRAX_USB_H
+#define __LINUX_ETRAX_USB_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+typedef struct USB_IN_Desc {
+	__u16 sw_len;
+	__u16 command;
+	unsigned long next;
+	unsigned long buf;
+	__u16 hw_len;
+	__u16 status;
+} USB_IN_Desc_t;
+
+typedef struct USB_SB_Desc {
+	__u16 sw_len;
+	__u16 command;
+	unsigned long next;
+	unsigned long buf;
+	__u32 dummy;
+} USB_SB_Desc_t;
+
+typedef struct USB_EP_Desc {
+	__u16 hw_len;
+	__u16 command;
+	unsigned long sub;
+	unsigned long nep;
+	__u32 dummy;
+} USB_EP_Desc_t;
+
+struct virt_root_hub {
+	int devnum;
+	void *urb;
+	void *int_addr;
+	int send;
+	int interval;
+	int numports;
+	struct timer_list rh_int_timer;
+	__u16 wPortChange_1;
+	__u16 wPortChange_2;
+	__u16 prev_wPortStatus_1;
+	__u16 prev_wPortStatus_2;
+};
+
+struct etrax_usb_intr_traffic {
+	int sleeping;
+	int error;
+	struct wait_queue *wq;
+};
+
+typedef struct etrax_usb_hc {
+	struct usb_bus *bus;
+	struct virt_root_hub rh;
+	struct etrax_usb_intr_traffic intr;
+} etrax_hc_t;
+
+typedef enum {idle, eot, nodata}  etrax_usb_rx_state_t;
+
+typedef struct etrax_usb_urb_priv {
+	USB_SB_Desc_t *first_sb;
+	__u32 rx_offset;
+	etrax_usb_rx_state_t rx_state;
+	__u8 eot;
+	struct list_head ep_in_list;
+} etrax_urb_priv_t;
+
+
+struct usb_reg_context
+{
+	etrax_hc_t *hc;
+	__u32 r_usb_epid_attn;
+	__u8 r_usb_status;
+	__u32 r_usb_rh_port_status_1;
+	__u32 r_usb_rh_port_status_2;
+	__u32 r_usb_irq_mask_read;
+	struct tq_struct usb_bh;
+#if 0
+	__u32 r_usb_ept_data[32];
+#endif
+};
+
+struct in_chunk
+{
+	void *data;
+	int length;
+	char epid;
+	struct list_head list;
+};
+
+  
+/* --------------------------------------------------------------------------- 
+   Virtual Root HUB 
+   ------------------------------------------------------------------------- */
+/* destination of request */
+#define RH_INTERFACE               0x01
+#define RH_ENDPOINT                0x02
+#define RH_OTHER                   0x03
+
+#define RH_CLASS                   0x20
+#define RH_VENDOR                  0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS           0x0080
+#define RH_CLEAR_FEATURE        0x0100
+#define RH_SET_FEATURE          0x0300
+#define RH_SET_ADDRESS		0x0500
+#define RH_GET_DESCRIPTOR	0x0680
+#define RH_SET_DESCRIPTOR       0x0700
+#define RH_GET_CONFIGURATION	0x0880
+#define RH_SET_CONFIGURATION	0x0900
+#define RH_GET_STATE            0x0280
+#define RH_GET_INTERFACE        0x0A80
+#define RH_SET_INTERFACE        0x0B00
+#define RH_SYNC_FRAME           0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP               0x2000
+
+
+/* Hub port features */
+#define RH_PORT_CONNECTION         0x00
+#define RH_PORT_ENABLE             0x01
+#define RH_PORT_SUSPEND            0x02
+#define RH_PORT_OVER_CURRENT       0x03
+#define RH_PORT_RESET              0x04
+#define RH_PORT_POWER              0x08
+#define RH_PORT_LOW_SPEED          0x09
+#define RH_C_PORT_CONNECTION       0x10
+#define RH_C_PORT_ENABLE           0x11
+#define RH_C_PORT_SUSPEND          0x12
+#define RH_C_PORT_OVER_CURRENT     0x13
+#define RH_C_PORT_RESET            0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER       0x00
+#define RH_C_HUB_OVER_CURRENT      0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP    0x00
+#define RH_ENDPOINT_STALL          0x01
+
+/* Our Vendor Specific feature */
+#define RH_REMOVE_EP               0x00
+
+
+#define RH_ACK                     0x01
+#define RH_REQ_ERR                 -1
+#define RH_NACK                    0x00
+
+#define min(a,b) (((a)<(b))?(a):(b))
+
+/* Field definitions for */
+
+#define USB_IN_command__eol__BITNR      0 /* command macros */
+#define USB_IN_command__eol__WIDTH      1
+#define USB_IN_command__eol__no         0
+#define USB_IN_command__eol__yes        1
+
+#define USB_IN_command__intr__BITNR     3
+#define USB_IN_command__intr__WIDTH     1
+#define USB_IN_command__intr__no        0
+#define USB_IN_command__intr__yes       1
+
+#define USB_IN_status__eop__BITNR       1 /* status macros. */
+#define USB_IN_status__eop__WIDTH       1
+#define USB_IN_status__eop__no          0
+#define USB_IN_status__eop__yes         1
+
+#define USB_IN_status__eot__BITNR       5
+#define USB_IN_status__eot__WIDTH       1
+#define USB_IN_status__eot__no          0
+#define USB_IN_status__eot__yes         1
+
+#define USB_IN_status__error__BITNR     6
+#define USB_IN_status__error__WIDTH     1
+#define USB_IN_status__error__no        0
+#define USB_IN_status__error__yes       1
+
+#define USB_IN_status__nodata__BITNR    7
+#define USB_IN_status__nodata__WIDTH    1
+#define USB_IN_status__nodata__no       0
+#define USB_IN_status__nodata__yes      1
+
+#define USB_IN_status__epid__BITNR      8
+#define USB_IN_status__epid__WIDTH      5
+
+#define USB_EP_command__eol__BITNR      0
+#define USB_EP_command__eol__WIDTH      1
+#define USB_EP_command__eol__no         0
+#define USB_EP_command__eol__yes        1
+
+#define USB_EP_command__eof__BITNR      1
+#define USB_EP_command__eof__WIDTH      1
+#define USB_EP_command__eof__no         0
+#define USB_EP_command__eof__yes        1
+
+#define USB_EP_command__intr__BITNR     3
+#define USB_EP_command__intr__WIDTH     1
+#define USB_EP_command__intr__no        0
+#define USB_EP_command__intr__yes       1
+
+#define USB_EP_command__enable__BITNR   4
+#define USB_EP_command__enable__WIDTH   1
+#define USB_EP_command__enable__no      0
+#define USB_EP_command__enable__yes     1
+
+#define USB_EP_command__hw_valid__BITNR 5
+#define USB_EP_command__hw_valid__WIDTH 1
+#define USB_EP_command__hw_valid__no    0
+#define USB_EP_command__hw_valid__yes   1
+
+#define USB_EP_command__epid__BITNR     8
+#define USB_EP_command__epid__WIDTH     5
+
+#define USB_SB_command__eol__BITNR      0 /* command macros. */
+#define USB_SB_command__eol__WIDTH      1
+#define USB_SB_command__eol__no         0
+#define USB_SB_command__eol__yes        1
+
+#define USB_SB_command__eot__BITNR      1
+#define USB_SB_command__eot__WIDTH      1
+#define USB_SB_command__eot__no         0
+#define USB_SB_command__eot__yes        1
+
+#define USB_SB_command__intr__BITNR     3
+#define USB_SB_command__intr__WIDTH     1
+#define USB_SB_command__intr__no        0
+#define USB_SB_command__intr__yes       1
+
+#define USB_SB_command__tt__BITNR       4
+#define USB_SB_command__tt__WIDTH       2
+#define USB_SB_command__tt__zout        0
+#define USB_SB_command__tt__in          1
+#define USB_SB_command__tt__out         2
+#define USB_SB_command__tt__setup       3
+
+
+#define USB_SB_command__rem__BITNR      8
+#define USB_SB_command__rem__WIDTH      6
+
+#define USB_SB_command__full__BITNR     6
+#define USB_SB_command__full__WIDTH     1
+#define USB_SB_command__full__no        0
+#define USB_SB_command__full__yes       1
+
+#endif
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/entry.S linux/arch/cris/kernel/entry.S
--- v2.4.3/linux/arch/cris/kernel/entry.S	Fri Mar  2 18:38:40 2001
+++ linux/arch/cris/kernel/entry.S	Fri Apr  6 10:42:55 2001
@@ -1,12 +1,30 @@
-/* $Id: entry.S,v 1.11 2001/01/10 21:13:29 bjornw Exp $
+/* $Id: entry.S,v 1.15 2001/03/05 13:14:30 bjornw Exp $
  *
  *  linux/arch/cris/entry.S
  *
- *  Copyright (C) 2000 Axis Communications AB
+ *  Copyright (C) 2000, 2001 Axis Communications AB
  *
  *  Authors:	Bjorn Wesen (bjornw@axis.com)
  *
  *  $Log: entry.S,v $
+ *  Revision 1.15  2001/03/05 13:14:30  bjornw
+ *  Spelling fix
+ *
+ *  Revision 1.14  2001/02/23 08:36:36  perf
+ *  New ABI; syscallnr=r9, arg5=mof, arg6=srp.
+ *  Corrected tracesys call check.
+ *
+ *  Revision 1.13  2001/02/15 08:40:55  perf
+ *  H-P by way of perf;
+ *  - (_system_call): Don't read system call function address into r1.
+ *  - (RBFExit): There is no such thing as a null pop.  Adjust sp by addq.
+ *  - (_system_call): Don't use r10 and don't save and restore it.
+ *  - (THREAD_ESP0): New constant.
+ *  - (_system_call): Inline set_esp0.
+ *
+ *  Revision 1.12  2001/01/31 17:56:25  orjanf
+ *  Added definition of LTASK_PID and made it global.
+ *
  *  Revision 1.11  2001/01/10 21:13:29  bjornw
  *  SYMBOL_NAME is defined incorrectly for the compiler options we currently use
  *
@@ -79,7 +97,8 @@
 	.globl _mmu_bus_fault
 				
 	.globl _sys_call_table
-		
+	
+	.globl LTASK_PID	
 	;; syscall error codes
 	
 LENOSYS = 38
@@ -90,7 +109,17 @@
 LTASK_SIGPENDING  =  8
 LTASK_NEEDRESCHED = 20
 LTASK_PTRACE      = 24
+LTASK_PID         = 105
+
+	;; process bits for ptrace
 
+PT_TRACESYS_BIT	  = 1
+
+	;; Offset for esp0 into task_struct: current->thread.esp0.
+	;; FIXME: In need of padding somewhere, to get dword-alignment.
+
+THREAD_ESP0	  = 597
+	
 	;; some pt_regs offsets (from ptrace.h)
 	
 LORIG_R10	= 4
@@ -98,8 +127,8 @@
 LR12		= 12
 LR11		= 16
 LR10		= 20
-LR1		= 56
-LR0		= 60	
+LR9		= 24
+LMOF		= 64
 LDCCR		= 68
 LSRP		= 72
 LIRP		= 76
@@ -124,7 +153,7 @@
 	nop
 	ba	ret_with_reschedule  ; go back but check schedule and signals first 
 	nop
-		
+
 reschedule:
 	;; keep r9 intact
 	push	r9
@@ -170,41 +199,38 @@
 	push	r10		; push orig_r10
 	clear.d [sp=sp-4]	; frametype == 0, normal stackframe
 	
-	move.d	r10,r2		; save for later
-	
-	movs.w	-LENOSYS,r10
-	move.d	r10,[sp+LR10]	; put the default return value in r10 in the frame
-	
-	move.d	sp,r10
-	jsr	_set_esp0	; save top of frame (clobbers r9...)
+	movs.w	-LENOSYS,r0
+	move.d	r0,[sp+LR10]	; put the default return value in r10 in the frame
+
+	;; Perform "current->thread.esp0 = sp".
+	;; This used to be a separate function; set_esp0(ssp).
+	movs.w -8192,r0		; THREAD_SIZE == 8192
+	and.d sp,r0
+
+	move.d sp,[r0+THREAD_ESP0]
 
 	;; check if this process is syscall-traced
 
-	move.d	sp, r10
-	and.d	-8192, r10		; THREAD_SIZE == 8192
-	move.d	[r10+LTASK_PTRACE],r10
-	btstq	2, r10	                ; PT_TRACESYS
+	move.d	[r0+LTASK_PTRACE],r0
+	btstq	PT_TRACESYS_BIT, r0
 	bmi	tracesys
 	nop	
 
 	;; check for sanity in the requested syscall number
 	
-	cmpu.w	NR_syscalls,r1	
+	cmpu.w	NR_syscalls,r9	
 	bcc	_ret_from_sys_call
-	lslq	2,r1		;  multiply by 4, in the delay slot
-
-	;; read the system call vector into r1
-	
-	move.d	[r1+_sys_call_table],r1	
+	lslq	2,r9		;  multiply by 4, in the delay slot
 
-	;; the parameter carrying registers r11, r12 and 13 are intact - restore r10.
-	;; the fifth parameter (if any) was in r0, and we need to put it on the stack
+	;; the parameter carrying registers r10, r11, r12 and 13 are intact.
+	;; the fifth and sixth parameters (if any) was in mof and srp 
+	;; respectively, and we need to put them on the stack.
 
-	push	r0
-	move.d	r2,r10
+	push	srp
+	push	mof
 	
-	jsr	r1		; actually call the corresponding system call
-	addq	4,sp		; pop the r0 parameter
+	jsr	[r9+_sys_call_table]	; actually do the system call
+	addq	2*4,sp		; pop the mof and srp parameters
 	move.d	r10,[sp+LR10]	; save the return value
 
 	moveq	1,r9		; "parameter" to ret_from_sys_call to show it was a sys call
@@ -269,10 +295,8 @@
 	;; just get the PC value to restart it with, and skip the rest of
 	;; the frame.
 	pop	irp		; fixup location will be here
-	pop	p8		; null pop
-	pop	p8		; null pop
 	reti			; return to IRP, taking U-flag into account
-	pop	p8		; null pop in delayslot
+	addq	12,sp		; Skip rest of SBFS frame.
 
 
 tracesys:
@@ -289,30 +313,32 @@
 
 	;; check for sanity in the requested syscall number
 
-	move.d	[sp+LR1], r1
+	move.d	[sp+LR9], r9
 	movs.w	-LENOSYS, r10
-	cmpu.w	NR_syscalls,r1	
+	cmpu.w	NR_syscalls,r9	
 	bcc	1f
-	lslq	2,r1		;  multiply by 4, in the delay slot
+	lslq	2,r9		;  multiply by 4, in the delay slot
 
-	;; read the system call vector entry into r1
+	;; read the system call vector entry into r9
 	
-	move.d	[r1+_sys_call_table],r1
+	move.d	[r9+_sys_call_table],r9
 
-	;; restore r10, r11, r12, r13 and r0 into the needed registers
+	;; restore r10, r11, r12, r13, mof and srp into the needed registers
 
 	move.d	[sp+LORIG_R10], r10  ; LR10 is already filled with -LENOSYS
 	move.d	[sp+LR11],      r11
 	move.d	[sp+LR12],      r12
 	move.d	[sp+LR13],      r13
-	move.d	[sp+LR0],       r0
+	move	[sp+LMOF],      mof
+	move	[sp+LSRP],      srp
 
-	;; the fifth parameter needs to be put on the stack for the system
-	;; call to find it
+	;; the fifth and sixth parameters needs to be put on the stack for
+	;; the system call to find them
 
-	push	r0
-	jsr	r1		; actually call the system-call
-	addq	4,sp		; pop the r0 parameter
+	push	srp
+	push	mof
+	jsr	r9		; actually call the system-call
+	addq	2*4,sp		; pop the r0 parameter
 
 1:	move.d	r10,[sp+LR10]	; save the return value
 
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/head.S linux/arch/cris/kernel/head.S
--- v2.4.3/linux/arch/cris/kernel/head.S	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/head.S	Fri Apr  6 10:42:55 2001
@@ -1,46 +1,75 @@
-	;; $Id: head.S,v 1.11 2001/01/16 16:31:38 bjornw Exp $
-	;; 
-	;; Head of the kernel - alter with care
-	;;
-	;; Copyright (C) 2000, 2001 Axis Communications AB
-	;;
-	;; Authors:	Bjorn Wesen (bjornw@axis.com)
-	;; 
-	;; $Log: head.S,v $
-	;; Revision 1.11  2001/01/16 16:31:38  bjornw
-	;; * Changed name and semantics of running_from_flash to romfs_in_flash,
-	;;   set by head.S to indicate to setup.c whether there is a cramfs image
-	;;   after the kernels BSS or not. Should work for all three boot-cases
-	;;   (DRAM with cramfs in DRAM, DRAM with cramfs in flash (compressed boot),
-	;;    and flash with cramfs in flash)
-	;;
-	;; Revision 1.10  2001/01/16 14:12:21  bjornw
-	;; * Check for cramfs start passed in r9 from the decompressor, if all other
-	;;   cramfs options fail (if we boot from DRAM but don't find a cramfs image
-	;;   after the kernel in DRAM, it is probably still in the flash)
-	;; * Check magic in cramfs detection when booting from flash directly
-	;;
-	;; Revision 1.9  2001/01/15 17:17:02  bjornw
-	;; * Corrected the code that detects the cramfs lengths
-	;; * Added a comment saying that the above does not work due to other
-	;;   reasons..
-	;;
-	;; Revision 1.8  2001/01/15 16:27:51  jonashg
-	;; Made boot after flashing work.
-	;; * end destination is __vmlinux_end in RAM.
-	;; * _romfs_start moved because of virtual memory.
-	;;
-	;; Revision 1.7  2000/11/21 13:55:29  bjornw
-	;; Use CONFIG_CRIS_LOW_MAP for the low VM map instead of explicit CPU type
-	;;
-	;; Revision 1.6  2000/10/06 12:36:55  bjornw
-	;; Forgot swapper_pg_dir when changing memory map..
-	;;
-	;; Revision 1.5  2000/10/04 16:49:30  bjornw
-	;; * Fixed memory mapping in LX
-	;; * Check for cramfs instead of romfs
-	;;
-	;;
+/* $Id: head.S,v 1.20 2001/02/23 12:47:56 bjornw Exp $
+ * 
+ * Head of the kernel - alter with care
+ *
+ * Copyright (C) 2000, 2001 Axis Communications AB
+ *
+ * Authors:	Bjorn Wesen (bjornw@axis.com)
+ * 
+ * $Log: head.S,v $
+ * Revision 1.20  2001/02/23 12:47:56  bjornw
+ * MMU regs during LOW_MAP updated to reflect a newer reality
+ *
+ * Revision 1.19  2001/02/19 11:12:07  bjornw
+ * Changed comment header format
+ *
+ * Revision 1.18  2001/02/15 07:25:38  starvik
+ * Added support for synchronous serial ports
+ *
+ * Revision 1.17  2001/02/08 15:53:13  starvik
+ * Last commit removed some important ifdefs
+ *
+ * Revision 1.16  2001/02/08 15:20:38  starvik
+ * Include dram_init.S as inline
+ *
+ * Revision 1.15  2001/01/29 18:12:01  bjornw
+ * Corrected some comments
+ *
+ * Revision 1.14  2001/01/29 13:11:29  starvik
+ * Include dram_init.S (with DRAM/SDRAM initialization)
+ *
+ * Revision 1.13  2001/01/23 14:54:57  markusl
+ * Updated for USB
+ * i.e. added r_gen_config settings
+ *
+ * Revision 1.12  2001/01/19 16:16:29  perf
+ * Added temporary mapping of 0x0c->0x0c to avoid flash loading confusion.
+ * Renamed serial options from ETRAX100 to ETRAX.
+ *
+ * Revision 1.11  2001/01/16 16:31:38  bjornw
+ * * Changed name and semantics of running_from_flash to romfs_in_flash,
+ *   set by head.S to indicate to setup.c whether there is a cramfs image
+ *   after the kernels BSS or not. Should work for all three boot-cases
+ *   (DRAM with cramfs in DRAM, DRAM with cramfs in flash (compressed boot),
+ *    and flash with cramfs in flash)
+ *
+ * Revision 1.10  2001/01/16 14:12:21  bjornw
+ * * Check for cramfs start passed in r9 from the decompressor, if all other
+ *   cramfs options fail (if we boot from DRAM but don't find a cramfs image
+ *   after the kernel in DRAM, it is probably still in the flash)
+ * * Check magic in cramfs detection when booting from flash directly
+ *
+ * Revision 1.9  2001/01/15 17:17:02  bjornw
+ * * Corrected the code that detects the cramfs lengths
+ * * Added a comment saying that the above does not work due to other
+ *   reasons..
+ *
+ * Revision 1.8  2001/01/15 16:27:51  jonashg
+ * Made boot after flashing work.
+ * * end destination is __vmlinux_end in RAM.
+ * * _romfs_start moved because of virtual memory.
+ *
+ * Revision 1.7  2000/11/21 13:55:29  bjornw
+ * Use CONFIG_CRIS_LOW_MAP for the low VM map instead of explicit CPU type
+ *
+ * Revision 1.6  2000/10/06 12:36:55  bjornw
+ * Forgot swapper_pg_dir when changing memory map..
+ *
+ * Revision 1.5  2000/10/04 16:49:30  bjornw
+ * * Fixed memory mapping in LX
+ * * Check for cramfs instead of romfs
+ *
+ */
 	
 #include <linux/config.h>
 #define ASSEMBLER_MACROS_ONLY
@@ -82,13 +111,13 @@
 	;; slightly different. We also let the simulator get this mapping for now.
 
 #ifdef CONFIG_CRIS_LOW_MAP
-	move.d	0x0800b000, r0	; kseg mappings
+	move.d	0x0004b098, r0	; kseg mappings, temporary map of 0xc0->0x40
 	move.d	r0, [R_MMU_KBASE_HI]
 
 	move.d	0x04040000, r0	; temporary map of 0x40->0x40 and 0x00->0x00 
 	move.d	r0, [R_MMU_KBASE_LO]
 
-	move.d	0x80074871, r0	; mmu enable, segs e,b,6,5,4,0 segment mapped
+	move.d	0x80075c71, r0	; mmu enable, segs c,b,9,8,6,5,4,0 segment mapped
 	move.d	r0, [R_MMU_CONFIG]
 #else
 	move.d	0x0804b000, r0	; kseg mappings
@@ -131,24 +160,9 @@
 	jump	inram		; enter cached ram
 	
 inflash:
+	;; We need to initialze DRAM registers before we start using the DRAM
+#include "../lib/dram_init.S"	
 
-#ifndef CONFIG_SVINTO_SIM	
-
-	;; We need to setup the bus registers before we start using the DRAM
-
-	move.d   DEF_R_WAITSTATES, r0
-	move.d   r0, [R_WAITSTATES]
-
-	move.d   DEF_R_BUS_CONFIG, r0
-	move.d   r0, [R_BUS_CONFIG]
-  
-	move.d   DEF_R_DRAM_CONFIG, r0
-	move.d   r0, [R_DRAM_CONFIG]
-
-	move.d   DEF_R_DRAM_TIMING, r0
-	move.d   r0, [R_DRAM_TIMING]
-
-#endif
 	;; Copy text+data to DRAM
 	;; This is fragile - the calculation of r4 as the image size depends
 	;; on that the labels below actually are the first and last positions
@@ -357,27 +371,38 @@
 #if !defined(CONFIG_KGDB) && !defined(CONFIG_DMA_MEMCPY)
 	or.d	0x140000,r0	; DMA channels 6 and 7 to ser0, kgdb doesnt want DMA
 #endif
-#if !defined(CONFIG_KGDB) || !defined(CONFIG_DEBUG_PORT1)
+#if !defined(CONFIG_KGDB) || !defined(CONFIG_DEBUG_PORT1)	
 	or.d	0xc00000,r0	; DMA channels 8 and 9 to ser1, kgdb doesnt want DMA
-#endif
+#endif	
 #ifdef CONFIG_DMA_MEMCPY
 	or.d	0x003c0000,r0	; 6/7 memory-memory DMA
 #endif
-#ifdef CONFIG_ETRAX100_SERIAL_PORT2
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
 	or.d	0x2808,r0	; DMA channels 2 and 3 to serport 2, port 2 enabled
 #endif
-#ifdef CONFIG_ETRAX100_SERIAL_PORT3
+#if defined(CONFIG_ETRAX_SERIAL_PORT3) || defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
 	or.d	0x28100,r0	; DMA channels 4 and 5 to serport 3, port 3 enabled
-#endif
-#if defined(CONFIG_ETRAX100_PARALLEL_PORT0) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
+#endif	
+#if defined(CONFIG_ETRAX_PARALLEL_PORT0) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
 	or.w	0x4,r0	; parport 0 enabled using DMA 2/3
 #endif
-#if defined(CONFIG_ETRAX100_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
+#if defined(CONFIG_ETRAX_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
 	or.w	0x80,r0	; parport 1 enabled using DMA 4/5
 #endif
 #ifdef CONFIG_BLK_DEV_ETRAXIDE
 	or.d	0x3c02,r0	; DMA channels 2 and 3 to ATA, ATA enabled
 #endif
+	
+#ifdef CONFIG_ETRAX_USB_HOST_PORT1
+	or.d	0x20000000,r0	; Set the USB port 1 enable bit
+#endif
+#ifdef CONFIG_ETRAX_USB_HOST_PORT2
+	or.d	0x40000000,r0	; Set the USB port 2 enable bit
+#endif
+#ifdef CONFIG_ETRAX_USB_HOST
+	and.d	0xff3fffff,r0	; Connect DMA channels 8 and 9 to USB
+#endif
+	
 #ifdef CONFIG_JULIETTE
 	or.d	0x3c000,r0	; DMA channels 4 and 5 to EXTDMA0, for Juliette
 #ifndef CONFIG_BLK_DEV_ETRAXIDE
@@ -438,6 +463,9 @@
 	move.b	DEF_R_PORT_PB_DATA,r0
 	move.b	r0,[_port_pb_data_shadow]
 	move.b	r0,[R_PORT_PB_DATA]
+	move.d  0, r0
+	move.d  r0,[_port_pb_i2c_shadow]
+	move.d  r0, [R_PORT_PB_I2C]
 
 	moveq	0,r0
 	move.d	r0,[_port_g_data_shadow]
@@ -478,7 +506,7 @@
 	move.d	r0,[0x90000000]
 #endif
 	
-#ifdef CONFIG_ETRAX100_SERIAL_PORT3	
+#ifdef CONFIG_ETRAX_SERIAL_PORT3	
 	;; setup the serial port 3 at 115200 baud for debug purposes
 	
 	moveq	0,r0
@@ -497,8 +525,7 @@
 #endif /* CONFIG_SVINTO_SIM */
 
 	jump	_start_kernel	; jump into the C-function _start_kernel in init/main.c
-
-	
+		
 	.data
 _etrax_irv:	
 	.dword	0
@@ -508,7 +535,7 @@
 	.dword	0
 _romfs_in_flash:
 	.dword	0
-
+	
 	;; put some special pages at the beginning of the kernel aligned
 	;; to page boundaries - the kernel cannot start until after this
 
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/irq.c linux/arch/cris/kernel/irq.c
--- v2.4.3/linux/arch/cris/kernel/irq.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/irq.c	Fri Apr  6 10:42:55 2001
@@ -1,8 +1,8 @@
-/* $Id: irq.c,v 1.5 2000/08/17 15:35:15 bjornw Exp $
+/* $Id: irq.c,v 1.11 2001/02/27 13:52:52 bjornw Exp $
  *
  *	linux/arch/cris/kernel/irq.c
  *
- *      Copyright (c) 2000 Axis Communications AB
+ *      Copyright (c) 2000,2001 Axis Communications AB
  *
  *      Authors: Bjorn Wesen (bjornw@axis.com)
  *
@@ -30,7 +30,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 
 #include <asm/system.h>
@@ -160,6 +160,8 @@
 BUILD_IRQ(23, 0x800000)
 BUILD_IRQ(24, 0x1000000)
 BUILD_IRQ(25, 0x2000000)
+/* IRQ 26-30 are resereved */	
+BUILD_IRQ(31, 0x80000000)
  
 /*
  * Pointers to the low-level handlers 
@@ -172,7 +174,8 @@
 	IRQ12_interrupt, IRQ13_interrupt, NULL, NULL,	
 	IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt,	
 	IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt,	
-	IRQ24_interrupt, IRQ25_interrupt
+	IRQ24_interrupt, IRQ25_interrupt, NULL, NULL, NULL, NULL, NULL,
+	IRQ31_interrupt
 };
 
 static void (*sinterrupt[NR_IRQS])(void) = {
@@ -182,7 +185,8 @@
 	sIRQ12_interrupt, sIRQ13_interrupt, NULL, NULL,	
 	sIRQ16_interrupt, sIRQ17_interrupt, sIRQ18_interrupt, sIRQ19_interrupt,	
 	sIRQ20_interrupt, sIRQ21_interrupt, sIRQ22_interrupt, sIRQ23_interrupt,	
-	sIRQ24_interrupt, sIRQ25_interrupt
+	sIRQ24_interrupt, sIRQ25_interrupt, NULL, NULL, NULL, NULL, NULL,
+	sIRQ31_interrupt
 };
 
 static void (*bad_interrupt[NR_IRQS])(void) = {
@@ -198,7 +202,9 @@
 	bad_IRQ18_interrupt, bad_IRQ19_interrupt,
 	bad_IRQ20_interrupt, bad_IRQ21_interrupt,
 	bad_IRQ22_interrupt, bad_IRQ23_interrupt,
-	bad_IRQ24_interrupt, bad_IRQ25_interrupt
+	bad_IRQ24_interrupt, bad_IRQ25_interrupt,
+	NULL, NULL, NULL, NULL, NULL,
+	bad_IRQ31_interrupt
 };
 
 /*
@@ -212,7 +218,8 @@
 	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)
@@ -412,6 +419,8 @@
 */
 
 void system_call(void);  /* from entry.S */
+void gdb_handle_breakpoint(void); /* from traps.c */
+void do_sigtrap(void); /* also from traps.c */
 
 void init_IRQ(void)
 {
@@ -431,14 +440,22 @@
 
 	for(i = 0; i < NR_IRQS; i++)
 		irq_shortcuts[i] = NULL;
-	
-	for (i = 0; i < 256; i++)
-		etrax_irv->v[i] = weird_irq;
-      
+        
+        for (i = 0; i < 256; i++)
+               etrax_irv->v[i] = weird_irq;
+
+        /* the entries in the break vector contain actual code to be
+           executed by the associated break handler, rather than just a jump
+           address. therefore we need to setup a default breakpoint handler
+           for all breakpoints */
+
+	for (i = 0; i < 16; i++)
+                set_break_vector(i, do_sigtrap);
+        
 	/* set all etrax irq's to the bad handlers */
 	for (i = 2; i < NR_IRQS; i++)
 		set_int_vector(i, bad_interrupt[i], 0);
-
+        
 	/* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
 
 	set_int_vector(15, multiple_interrupt, 0);
@@ -456,12 +473,15 @@
 
 	set_break_vector(13, system_call);
 
+        /* setup a breakpoint handler for debugging used for both user and
+           kernel mode debugging  (which is why it is not inside an ifdef
+           CONFIG_KGDB) */
+        set_break_vector(8, gdb_handle_breakpoint);
+
 #ifdef CONFIG_KGDB
 	/* setup kgdb if its enabled, and break into the debugger */
-
 	kgdb_init();
-
 	breakpoint();
 #endif
 
-} 
+}
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/kgdb.c linux/arch/cris/kernel/kgdb.c
--- v2.4.3/linux/arch/cris/kernel/kgdb.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/kgdb.c	Fri Apr  6 10:42:55 2001
@@ -18,6 +18,12 @@
 *! Jul 21 1999  Bjorn Wesen     eLinux port
 *!
 *! $Log: kgdb.c,v $
+*! Revision 1.4  2001/02/23 13:45:19  bjornw
+*! config.h check
+*!
+*! Revision 1.3  2001/01/31 18:08:23  orjanf
+*! Removed kgdb_handle_breakpoint from being the break 8 handler.
+*!
 *! Revision 1.2  2001/01/12 14:22:25  orjanf
 *! Updated kernel debugging support to work with ETRAX 100LX.
 *!
@@ -43,7 +49,7 @@
 *!
 *!---------------------------------------------------------------------------
 *!
-*! $Id: kgdb.c,v 1.2 2001/01/12 14:22:25 orjanf Exp $
+*! $Id: kgdb.c,v 1.4 2001/02/23 13:45:19 bjornw Exp $
 *!
 *! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
 *!
@@ -1531,7 +1537,7 @@
 {
 	/* could initialize debug port as well but it's done in head.S already... */
 
-	set_break_vector(8, kgdb_handle_breakpoint);
+        /* breakpoint handler is now set in irq.c */
 	set_int_vector(8, kgdb_handle_serial, 0);
 	
 	enableDebugIRQ();
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/process.c linux/arch/cris/kernel/process.c
--- v2.4.3/linux/arch/cris/kernel/process.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/process.c	Fri Apr  6 10:42:55 2001
@@ -1,9 +1,9 @@
-/* $Id: process.c,v 1.8 2000/09/13 14:34:13 bjornw Exp $
+/* $Id: process.c,v 1.12 2001/02/27 13:52:52 bjornw Exp $
  * 
  *  linux/arch/cris/kernel/process.c
  *
  *  Copyright (C) 1995  Linus Torvalds
- *  Copyright (C) 2000  Axis Communications AB
+ *  Copyright (C) 2000, 2001  Axis Communications AB
  *
  *  Authors:   Bjorn Wesen (bjornw@axis.com)
  *
@@ -23,7 +23,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
@@ -71,11 +71,6 @@
 
 #define currentregs ((struct pt_regs *)current->thread.esp0)
 
-asmlinkage void set_esp0(unsigned long ssp)
-{
-	current->thread.esp0 = ssp;
-}
-
 void disable_hlt(void)
 {
 	hlt_counter++;
@@ -134,7 +129,7 @@
 	register long __a __asm__ ("r10");
 	
 	__asm__ __volatile__
-		("movu.w %1,r1\n\t"     /* r1 contains syscall number, to sys_clone */
+		("movu.w %1,r9\n\t"     /* r9 contains syscall number, to sys_clone */
 		 "clear.d r10\n\t"      /* r10 is argument 1 to clone */
 		 "move.d %2,r11\n\t"    /* r11 is argument 2 to clone, the flags */
 		 "break 13\n\t"         /* call sys_clone, this will fork */
@@ -143,14 +138,14 @@
 		 "nop\n\t"              /* delay slot */
 		 "move.d %4,r10\n\t"    /* set argument to function to call */
 		 "jsr %5\n\t"           /* call specified function */
-		 "movu.w %3,r1\n\t"     /* r1 is sys_exit syscall number */
+		 "movu.w %3,r9\n\t"     /* r9 is sys_exit syscall number */
 		 "moveq -1,r10\n\t"     /* Give a really bad exit-value */
 		 "break 13\n\t"         /* call sys_exit, killing the child */
 		 "1:\n\t"
 		 : "=r" (__a) 
 		 : "g" (__NR_clone), "r" (flags | CLONE_VM), "g" (__NR_exit),
 		   "r" (arg), "r" (fn) 
-		 : "r10", "r11", "r1");
+		 : "r10", "r11", "r9");
 	
 	return __a;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/semaphore.c linux/arch/cris/kernel/semaphore.c
--- v2.4.3/linux/arch/cris/kernel/semaphore.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/semaphore.c	Tue Apr 17 17:19:24 2001
@@ -127,112 +127,3 @@
 {
 	return waking_non_zero_trylock(sem);
 }
-
-/*
- * RW Semaphores
- */
-void
-__down_read(struct rw_semaphore *sem, int count)
-{
-	DOWN_VAR;
-
- retry_down:
-	if (count < 0) {
-		/* Wait for the lock to become unbiased.  Readers
-		   are non-exclusive.  */
-		
-		/* This takes care of granting the lock.  */
-		up_read(sem);
-
-		add_wait_queue(&sem->wait, &wait);
-		while (atomic_read(&sem->count) < 0) {
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if (atomic_read(&sem->count) >= 0)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_dec_return(&sem->count);
-		if (count <= 0)
-			goto retry_down;
-	} else {
-		add_wait_queue(&sem->wait, &wait);
-
-		while (1) {
-			if (test_and_clear_bit(0, &sem->granted))
-				break;
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if ((sem->granted & 1) == 0)
-				schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-	}
-}
-
-void
-__down_write(struct rw_semaphore *sem, int count)
-{
-	DOWN_VAR;
-
- retry_down:
-	if (count + RW_LOCK_BIAS < 0) {
-		up_write(sem);
-
-		add_wait_queue_exclusive(&sem->wait, &wait);
-	
-		while (atomic_read(&sem->count) < 0) {
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if (atomic_read(&sem->count) >= RW_LOCK_BIAS)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-		if (count != 0)
-			goto retry_down;
-	} else {
-		/* Put ourselves at the end of the list.  */
-		add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-		while (1) {
-			if (test_and_clear_bit(1, &sem->granted))
-				break;
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if ((sem->granted & 2) == 0)
-				schedule();
-		}
-
-		remove_wait_queue(&sem->write_bias_wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		/* If the lock is currently unbiased, awaken the sleepers.
-		   FIXME: This wakes up the readers early in a bit of a
-		   stampede -> bad!  */
-		if (atomic_read(&sem->count) >= 0)
-			wake_up(&sem->wait);
-	}
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-	if (readers) {
-		if (test_and_set_bit(0, &sem->granted))
-			BUG();
-		wake_up(&sem->wait);
-	} else {
-		if (test_and_set_bit(1, &sem->granted))
-			BUG();
-		wake_up(&sem->write_bias_wait);
-	}
-}
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/setup.c linux/arch/cris/kernel/setup.c
--- v2.4.3/linux/arch/cris/kernel/setup.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/setup.c	Fri Apr  6 10:42:55 2001
@@ -1,9 +1,9 @@
-/* $Id: setup.c,v 1.8 2001/01/16 16:31:38 bjornw Exp $
+/* $Id: setup.c,v 1.11 2001/03/02 15:52:03 bjornw Exp $
  *
  *  linux/arch/cris/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
- *  Copyright (c) 2000  Axis Communications AB
+ *  Copyright (c) 2001  Axis Communications AB
  */
 
 /*
@@ -17,7 +17,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
@@ -75,7 +75,8 @@
  *
  */
 
-void __init setup_arch(char **cmdline_p)
+void __init 
+setup_arch(char **cmdline_p)
 {
         unsigned long bootmap_size;
 	unsigned long start_pfn, max_pfn;
@@ -179,7 +180,7 @@
 
 	/* give credit for the CRIS port */
 
-	printk("Linux/CRIS port on ETRAX 100LX (c) 2000 Axis Communications AB\n");
+	printk("Linux/CRIS port on ETRAX 100LX (c) 2001 Axis Communications AB\n");
 
 }
 
@@ -192,6 +193,7 @@
 #define HAS_ATA		0x0020
 #define HAS_USB		0x0040
 #define HAS_IRQ_BUG	0x0080
+#define HAS_MMU_BUG     0x0100
 
 static struct cpu_info {
 	char *model;
@@ -214,7 +216,8 @@
 	{ "Simulator",     8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
 	{ "ETRAX 100",     8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG },
 	{ "ETRAX 100",     8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
-	{ "ETRAX 100LX",  8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU },
+	{ "ETRAX 100LX",  8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU | HAS_MMU_BUG },
+	{ "ETRAX 100LX v2",  8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU },
 	{ "Unknown",   0, 0 },
 };
 
@@ -241,6 +244,7 @@
 		       "cache size\t: %d kB\n"
 		       "fpu\t\t: %s\n"
 		       "mmu\t\t: %s\n"
+		       "mmu DMA bug\t: %s\n"
 		       "ethernet\t: %s Mbps\n"
 		       "token ring\t: %s\n"
 		       "scsi\t\t: %s\n"
@@ -253,6 +257,7 @@
 		       cpu_info[revision].cache,
 		       cpu_info[revision].flags & HAS_FPU ? "yes" : "no",
 		       cpu_info[revision].flags & HAS_MMU ? "yes" : "no",
+		       cpu_info[revision].flags & HAS_MMU_BUG ? "yes" : "no",
 		       cpu_info[revision].flags & HAS_ETHERNET100 ? "10/100" : "10",
 		       cpu_info[revision].flags & HAS_TOKENRING ? "4/16 Mbps" : "no",
 		       cpu_info[revision].flags & HAS_SCSI ? "yes" : "no",
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/signal.c linux/arch/cris/kernel/signal.c
--- v2.4.3/linux/arch/cris/kernel/signal.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/signal.c	Fri Apr  6 10:42:55 2001
@@ -38,9 +38,6 @@
 
 #define RESTART_CRIS_SYS(regs) regs->r10 = regs->orig_r10; regs->irp -= 2;
 
-int sys_wait4(pid_t pid, unsigned long *stat_addr,
-			 int options, unsigned long *ru);
-
 int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs);
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
@@ -391,9 +388,9 @@
 	} else {
 		/* trampoline - the desired return ip is the retcode itself */
 		return_ip = (unsigned long)&frame->retcode;
-		/* This is movu.w __NR_sigreturn, r1; break 13; */
+		/* This is movu.w __NR_sigreturn, r9; break 13; */
 		/* TODO: check byteorder */
-		err |= __put_user(0x1c5f,         (short *)(frame->retcode+0));
+		err |= __put_user(0x9c5f,         (short *)(frame->retcode+0));
 		err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+2));
 		err |= __put_user(0xe93d,         (short *)(frame->retcode+4));
 	}
@@ -453,9 +450,9 @@
 	} else {
 		/* trampoline - the desired return ip is the retcode itself */
 		return_ip = (unsigned long)&frame->retcode;
-		/* This is movu.w __NR_sigreturn, r1; break 13; */
+		/* This is movu.w __NR_sigreturn, r9; break 13; */
 		/* TODO: check byteorder */
-		err |= __put_user(0x1c5f,         (short *)(frame->retcode+0));
+		err |= __put_user(0x9c5f,         (short *)(frame->retcode+0));
 		err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+2));
 		err |= __put_user(0xe93d,         (short *)(frame->retcode+4));
 	}
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/sys_cris.c linux/arch/cris/kernel/sys_cris.c
--- v2.4.3/linux/arch/cris/kernel/sys_cris.c	Mon Mar 19 12:35:11 2001
+++ linux/arch/cris/kernel/sys_cris.c	Fri Apr  6 10:42:55 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_cris.c,v 1.3 2000/08/02 13:59:02 bjornw Exp $
+/* $Id: sys_cris.c,v 1.4 2001/01/31 14:55:58 perf Exp $
  *
  * linux/arch/cris/kernel/sys_etrax.c
  *
@@ -97,10 +97,22 @@
         return error;
 }
 
-asmlinkage unsigned long old_mmap(unsigned long addr, size_t len, int prot,
-                                  int flags, int fd, off_t offset)
-{
-        return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+asmlinkage unsigned long old_mmap(unsigned long *args)
+{        
+	unsigned long buffer[6];
+	int err = -EFAULT;
+
+	if (copy_from_user(&buffer, args, sizeof(buffer)))
+		goto out;
+
+	err = -EINVAL;
+	if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */
+		goto out;
+
+	err = do_mmap2(buffer[0], buffer[1], buffer[2], buffer[3],
+                       buffer[4], buffer[5] >> PAGE_SHIFT);
+out:
+	return err;
 }
 
 asmlinkage long
diff -u --recursive --new-file v2.4.3/linux/arch/cris/kernel/traps.c linux/arch/cris/kernel/traps.c
--- v2.4.3/linux/arch/cris/kernel/traps.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/traps.c	Fri Apr  6 10:42:55 2001
@@ -1,16 +1,19 @@
-/* $Id: traps.c,v 1.3 2000/10/04 16:50:06 bjornw Exp $
+/* $Id: traps.c,v 1.8 2001/02/23 13:45:20 bjornw Exp $
  *
  *  linux/arch/cris/traps.c
  *
- *  Etrax100 does not have any hardware traps, only IRQ's, which we setup
- *  in irq.c instead. Here we just define the die_if_kernel Oops'er.
- *
- *  Copyright (C) 2000 Axis Communications AB
+ *  Here we handle the break vectors not used by the system call 
+ *  mechanism, as well as some general stack/register dumping 
+ *  things.
+ * 
+ *  Copyright (C) 2000,2001 Axis Communications AB
  *
  *  Authors:   Bjorn Wesen
+ *             Orjan Friberg
  *
  */
 
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -35,7 +38,8 @@
 
 #define MODULE_RANGE (8*1024*1024)
 
-void show_stack(unsigned long *sp)
+void 
+show_stack(unsigned long *sp)
 {
         unsigned long *stack, addr, module_start, module_end;
         int i;
@@ -86,7 +90,8 @@
 #if 0
 /* displays a short stack trace */
 
-int show_stack()
+int 
+show_stack()
 {
 	unsigned long *sp = (unsigned long *)rdusp();
 	int i;
@@ -97,7 +102,8 @@
 }
 #endif
 
-void show_registers(struct pt_regs * regs)
+void 
+show_registers(struct pt_regs * regs)
 {
 	unsigned long usp = rdusp();
 
@@ -145,9 +151,8 @@
 #endif
 }
 
-
-
-void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+void 
+die_if_kernel(const char * str, struct pt_regs * regs, long err)
 {
 	if(user_mode(regs))
 		return;
@@ -160,8 +165,68 @@
 	do_exit(SIGSEGV);
 }
 
-void __init trap_init(void)
+void __init 
+trap_init(void)
 {
-  
 
 }
+
+/* Use static variables instead of the stack for temporary storage.  */
+static int saved_r0 = 0;
+static int saved_dccr = 0;
+
+asm ("
+  .global _gdb_handle_breakpoint
+  .global _do_sigtrap
+_gdb_handle_breakpoint:
+;;
+;; This handles a break instruction for entering a debug session.
+;;
+  move     dccr,[_saved_dccr]       ; Save dccr.
+  move.d   r0,[_saved_r0]           ; Save r0. "
+#ifdef CONFIG_KGDB
+" 
+  move     ccr,r0                   
+  btstq    8,r0                     ; Test the U-flag.
+  bmi      _ugdb_handle_breakpoint  ; Go to user mode debugging.
+  nop                               ; Delay slot.
+  move.d   [_saved_r0],r0           ; Restore r0.
+  move     [_saved_dccr],dccr       ; Restore dccr.
+  ba       _kgdb_handle_breakpoint  ; Go to kernel debugging.
+  nop                               ; Delay slot. "
+#endif
+" 
+_ugdb_handle_breakpoint:
+;;
+;; Yes, we could do a 'push brp' here and let gdb adjust the pc once it
+;; starts talking to the target again, but this way we avoid a 'P' packet.
+;;
+  move     brp,r0               ; Use r0 temporarily for calculation.
+  subq     2,r0                 ; Set to address of previous instruction.
+  move     r0,brp               ; Restore new brp.
+  move.d   [_saved_r0],r0       ; Restore r0.
+  move     [_saved_dccr],dccr   ; Restore dccr.
+
+_do_sigtrap:
+;; 
+;; SIGTRAP the process that executed the break instruction.
+;; Make a frame that Rexit in entry.S expects.
+;;
+  push     brp                  ; Push breakpoint return pointer.
+  push     srp                  ; Push subroutine return pointer.
+  push     dccr                 ; Push condition codes.
+  push     mof                  ; Push multiply overflow reg.
+  di                            ; Need to disable irq's at this point.
+  subq     14*4,sp              ; Make room for r0-r13.
+  movem    r13,[sp]             ; Push the r0-r13 registers.
+  push     r10                  ; Push orig_r10.
+  clear.d  [sp=sp-4]            ; Frametype - this is a normal stackframe.
+
+  movs.w   -8192,r9             ; THREAD_SIZE == 8192
+  and.d    sp,r9
+  move.d   [r9+LTASK_PID],r10   ; current->pid as arg1.
+  moveq    5,r11                ; SIGTRAP as arg2.
+  jsr      _sys_kill       
+
+  jump     _ret_from_intr       ; Use the return routine for interrupts.
+");
diff -u --recursive --new-file v2.4.3/linux/arch/cris/lib/checksum.S linux/arch/cris/lib/checksum.S
--- v2.4.3/linux/arch/cris/lib/checksum.S	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/lib/checksum.S	Fri Apr  6 10:42:55 2001
@@ -1,16 +1,21 @@
-	;; $Id: checksum.S,v 1.1 2000/07/10 16:25:21 bjornw Exp $
-	;; A fast checksum routine using movem
-	;; Copyright (c) 1998 Bjorn Wesen/Axis Communications AB
+/* $Id: checksum.S,v 1.4 2001/02/19 11:11:33 bjornw Exp $
+ * A fast checksum routine using movem
+ * Copyright (c) 1998-2001 Axis Communications AB
+ *
+ * csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
 
-	;; csum_partial(const unsigned char * buff, int len, unsigned int sum)
-	
 	.globl	_csum_partial
 _csum_partial:
 	
+	;; r10 - src
+	;; r11 - length
+	;; r12 - checksum
+
 	;; check for breakeven length between movem and normal word looping versions
 	
 	cmpu.w	80,r11
-	bcs	no_movem
+	blo	word_loop
 	nop
 
 	;; need to save the registers we use below in the movem loop
@@ -21,10 +26,6 @@
 	
 	;; do a movem checksum
 
-	;; r10 - src
-	;; r11 - length
-	;; r12 - checksum
-
 	subq	10*4,r11	; update length for the first loop
 	
 mloop:	movem	[r10+],r9	; read 10 longwords
@@ -65,23 +66,30 @@
 
 	addq	10*4,r11	; compensate for last loop underflowing length
 
-	;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below
-	
-	moveq	-1,r1		; put 0xffff in r1, faster than move.d 0xffff,r1
-	lsrq	16,r1
-	
-	move.d	r12,r0
-	lsrq	16,r0		; r0 = checksum >> 16
-	and.d	r1,r12		; checksum = checksum & 0xffff
-	add.d	r0,r12		; checksum += r0
-	move.d	r12,r0		; do the same again, maybe we got a carry last add
-	lsrq	16,r0
-	and.d	r1,r12
-	add.d	r0,r12
-	
 	movem	[sp+],r8	; restore regs
 
-no_movem:
+word_loop:
+	;; only fold if there is anything to fold.
+
+	cmpq	0,r12
+	beq	no_fold
+
+	;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below.
+	;; r9 and r13 can be used as temporaries.
+	
+	moveq	-1,r9		; put 0xffff in r9, faster than move.d 0xffff,r9
+	lsrq	16,r9
+	
+	move.d	r12,r13
+	lsrq	16,r13		; r13 = checksum >> 16
+	and.d	r9,r12		; checksum = checksum & 0xffff
+	add.d	r13,r12		; checksum += r13
+	move.d	r12,r13		; do the same again, maybe we got a carry last add
+	lsrq	16,r13
+	and.d	r9,r12
+	add.d	r13,r12
+
+no_fold:
 	cmpq	2,r11
 	blt	no_words
 	nop
@@ -110,4 +118,3 @@
 	ret
 	move.d	r12, r10
 		
-	
\ No newline at end of file
diff -u --recursive --new-file v2.4.3/linux/arch/cris/lib/checksumcopy.S linux/arch/cris/lib/checksumcopy.S
--- v2.4.3/linux/arch/cris/lib/checksumcopy.S	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/lib/checksumcopy.S	Fri Apr  6 10:42:55 2001
@@ -1,19 +1,25 @@
-	;; $Id: checksumcopy.S,v 1.2 2000/08/08 16:57:31 bjornw Exp $
-	;; A fast checksum+copy routine using movem
-	;; Copyright (c) 1998, 2000 Axis Communications AB
-	;;
-	;; Authors:	Bjorn Wesen
-	;; 
-	;; csum_partial_copy_nocheck(const char *src, char *dst,
-	;;		             int len, unsigned int sum)
+/* $Id: checksumcopy.S,v 1.4 2001/02/19 11:11:34 bjornw Exp $
+ * A fast checksum+copy routine using movem
+ * Copyright (c) 1998, 2001 Axis Communications AB
+ *
+ * Authors:	Bjorn Wesen
+ * 
+ * csum_partial_copy_nocheck(const char *src, char *dst,
+ *		             int len, unsigned int sum)
+ */
 
 	.globl	_csum_partial_copy_nocheck
 _csum_partial_copy_nocheck:	
 	
+	;; r10 - src
+	;; r11 - dst
+	;; r12 - length
+	;; r13 - checksum
+
 	;; check for breakeven length between movem and normal word looping versions
 	
 	cmpu.w	80,r12
-	bcs	no_movem
+	blo	word_loop
 	nop
 
 	;; need to save the registers we use below in the movem loop
@@ -24,11 +30,6 @@
 	
 	;; do a movem copy and checksum
 
-	;; r10 - src
-	;; r11 - dst
-	;; r12 - length
-	;; r13 - checksum
-
 	subq	10*4,r12	; update length for the first loop
 	
 mloop:	movem	[r10+],r9	; read 10 longwords
@@ -61,6 +62,8 @@
 	
 	ax
 	addq	0,r13
+	ax			; do it again, since we might have generated a carry
+	addq	0,r13
 
 	subq	10*4,r12
 	bge	mloop
@@ -68,23 +71,27 @@
 
 	addq	10*4,r12	; compensate for last loop underflowing length
 
+	movem	[sp+],r8	; restore regs
+
+word_loop:
+	;; only fold if there is anything to fold.
+
+	cmpq	0,r13
+	beq	no_fold
+
 	;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below
+	;; r9 can be used as temporary.
 	
-	moveq	-1,r1		; put 0xffff in r1, faster than move.d 0xffff,r1
-	lsrq	16,r1
-	
-	move.d	r13,r0
-	lsrq	16,r0		; r0 = checksum >> 16
-	and.d	r1,r13		; checksum = checksum & 0xffff
-	add.d	r0,r13		; checksum += r0
-	move.d	r13,r0		; do the same again, maybe we got a carry last add
-	lsrq	16,r0
-	and.d	r1,r13
-	add.d	r0,r13
+	move.d	r13,r9
+	lsrq	16,r9		; r0 = checksum >> 16
+	and.d	0xffff,r13	; checksum = checksum & 0xffff
+	add.d	r9,r13		; checksum += r0
+	move.d	r13,r9		; do the same again, maybe we got a carry last add
+	lsrq	16,r9
+	and.d	0xffff,r13
+	add.d	r9,r13
 	
-	movem	[sp+],r8	; restore regs
-		
-no_movem:
+no_fold:
 	cmpq	2,r12
 	blt	no_words
 	nop
@@ -117,4 +124,4 @@
 	ret
 	move.d	r13, r10
 		
-	
\ No newline at end of file
+	
diff -u --recursive --new-file v2.4.3/linux/arch/cris/lib/dram_init.S linux/arch/cris/lib/dram_init.S
--- v2.4.3/linux/arch/cris/lib/dram_init.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/dram_init.S	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,123 @@
+	;; $Id: dram_init.S,v 1.2 2001/02/08 15:20:00 starvik Exp $
+	;; 
+	;; DRAM/SDRAM initialization - alter with care
+	;; This file is intended to be included from other assembler files
+	;;
+	;; Copyright (C) 2000 Axis Communications AB
+	;;
+	;; Authors:  Mikael Starvik (starvik@axis.com)	
+	;;           Bjorn Wesen (bjornw@axis.com)
+	;; 
+	;; $Log: dram_init.S,v $
+	;; Revision 1.2  2001/02/08 15:20:00  starvik
+	;; Corrected SDRAM initialization
+	;; Should now be included as inline
+	;;
+	;; Revision 1.1  2001/01/29 13:08:02  starvik
+	;; Initial version
+	;; This file should be included from all assembler files that needs to
+	;; initialize DRAM/SDRAM.
+	;;
+	;;
+	;;
+
+#include <linux/config.h>
+
+#ifndef CONFIG_SVINTO_SIM	
+	move.d   DEF_R_WAITSTATES, r0
+	move.d   r0, [R_WAITSTATES]
+
+	move.d   DEF_R_BUS_CONFIG, r0
+	move.d   r0, [R_BUS_CONFIG]
+	
+#ifndef CONFIG_SDRAM
+	move.d   DEF_R_DRAM_CONFIG, r0
+	move.d   r0, [R_DRAM_CONFIG]
+
+	move.d   DEF_R_DRAM_TIMING, r0
+	move.d   r0, [R_DRAM_TIMING]
+#else	
+	; Refer to ETRAX 100LX Designers Reference for a description of SDRAM initialization
+	
+	; Bank configuration
+        move.d   DEF_R_SDRAM_CONFIG, r0
+	move.d   r0, [R_SDRAM_CONFIG]
+
+	; Calculate value of mrs_data 
+	; cas_delay = 2 && bus_width = 32 => 0x40
+	; cas_delay = 3 && bus_width = 32 => 0x60
+	; cas_delay = 2 && bus_width = 16 => 0x20
+	; cas_delay = 3 && bus_width = 16 => 0x30
+	
+	move.d   0x40, r2       ; Assume 32 bits and cas_delay = 2
+	move.d   DEF_R_SDRAM_TIMING, r1
+	and.d    0x0c, r1	; Get cas delay
+	cmp.d    0x08, r1	; cas_delay = 2?
+        beq      bw_check
+	nop
+	or.d     0x20, r2       ; cas_delay = 3
+bw_check:
+	move.d   DEF_R_SDRAM_CONFIG, r1
+	and.d    0x800000, r1	; DRAM width is bit 23
+	bne      set_timing
+	nop
+	lsrq     1, r2		;  16 bits. Shift down value.
+
+	; Set timing parameters. Starts master clock
+set_timing:
+	move.d   DEF_R_SDRAM_TIMING, r1
+	or.d     0x80000000, r1	; Make sure sdram enable bit is set
+	lslq     16, r2		; mrs data starts at bit 16
+	or.d     r2, r1 
+	move.d   r1, [R_SDRAM_TIMING]	
+		
+	; Wait 200ns
+	move.d   10, r2
+sdram_loop:
+	bne      sdram_loop
+	subq     1, r2
+	
+	; Issue initialization command sequence
+	move.d   sdram_commands_start, r2
+	move.d   sdram_commands_end,  r3
+command_loop:
+	clear.d  r4
+	move.b   [r2+], r4
+	lslq     9, r4		; Command starts at bit 9
+	or.d     r1, r4
+	move.d   r4, [R_SDRAM_TIMING]
+	nop			; Wait five nop cycles between each command
+	nop
+	nop
+	nop
+	nop
+	cmp.d    r2, r3
+	bne      command_loop
+	nop
+	ba       sdram_commands_end
+	nop
+
+sdram_commands_start:
+	.byte   3	; Precharge
+	.byte   0       ; nop
+	.byte   2	; refresh
+	.byte   0	; nop
+	.byte   2	; refresh
+	.byte   0	; nop
+	.byte   2	; refresh
+	.byte   0	; nop
+	.byte   2	; refresh
+	.byte   0	; nop
+	.byte   2	; refresh
+	.byte   0	; nop
+	.byte   2	; refresh
+	.byte   0	; nop
+	.byte   2	; refresh
+	.byte   0	; nop
+	.byte   2	; refresh
+	.byte   0	; nop
+	.byte   1	; mrs
+	.byte   0	; nop 
+sdram_commands_end:		
+#endif
+#endif
diff -u --recursive --new-file v2.4.3/linux/arch/cris/mm/Makefile linux/arch/cris/mm/Makefile
--- v2.4.3/linux/arch/cris/mm/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/mm/Makefile	Fri Apr  6 10:42:55 2001
@@ -8,6 +8,6 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-obj-y	 := init.o fault.o tlb.o extable.o
+obj-y	 := init.o fault.o tlb.o extable.o ioremap.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/cris/mm/fault.c linux/arch/cris/mm/fault.c
--- v2.4.3/linux/arch/cris/mm/fault.c	Mon Mar 19 12:35:11 2001
+++ linux/arch/cris/mm/fault.c	Fri Apr  6 10:42:55 2001
@@ -6,6 +6,9 @@
  *  Authors:  Bjorn Wesen 
  * 
  *  $Log: fault.c,v $
+ *  Revision 1.9  2001/03/05 13:22:20  bjornw
+ *  Spell-fix and fix in vmalloc_fault handling
+ *
  *  Revision 1.8  2000/11/22 14:45:31  bjornw
  *  * 2.4.0-test10 removed the set_pgdir instantaneous kernel global mapping
  *    into all processes. Instead we fill in the missing PTE entries on demand.
@@ -301,7 +304,7 @@
 	/* Are we prepared to handle this kernel fault?
 	 *
 	 * (The kernel has valid exception-points in the source 
-	 *  when it acesses user-memory. When it fails in one
+	 *  when it accesses user-memory. When it fails in one
 	 *  of those points, we find it in a table and do a jump
 	 *  to some fixup code that loads an appropriate error
 	 *  code)
diff -u --recursive --new-file v2.4.3/linux/arch/cris/mm/init.c linux/arch/cris/mm/init.c
--- v2.4.3/linux/arch/cris/mm/init.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/mm/init.c	Fri Apr  6 10:42:55 2001
@@ -2,11 +2,22 @@
  *  linux/arch/cris/mm/init.c
  *
  *  Copyright (C) 1995  Linus Torvalds
- *  Copyright (C) 2000  Axis Communications AB
+ *  Copyright (C) 2000,2001  Axis Communications AB
  *
  *  Authors:  Bjorn Wesen (bjornw@axis.com)
  *
  *  $Log: init.c,v $
+ *  Revision 1.18  2001/02/23 12:46:44  bjornw
+ *  * 0xc was not CSE1; 0x8 is, same as uncached flash, so we move the uncached
+ *    flash during CRIS_LOW_MAP from 0xe to 0x8 so both the flash and the I/O
+ *    is mapped straight over (for !CRIS_LOW_MAP the uncached flash is still 0xe)
+ *
+ *  Revision 1.17  2001/02/22 15:05:21  bjornw
+ *  Map 0x9 straight over during LOW_MAP to allow for memory mapped LEDs
+ *
+ *  Revision 1.16  2001/02/22 15:02:35  bjornw
+ *  Map 0xc straight over during LOW_MAP to allow for memory mapped I/O
+ *
  *  Revision 1.15  2001/01/10 21:12:10  bjornw
  *  loops_per_sec -> loops_per_jiffy
  *
@@ -287,16 +298,19 @@
 	 * The Juliette chip is mapped at 0xa so we pass that segment straight
 	 * through. We cannot vremap it because the vmalloc area is below 0x8
 	 * and Juliette needs an uncached area above 0x8.
+	 *
+	 * Same thing with 0xc and 0x9, which is memory-mapped I/O on some boards.
+	 * We map them straight over in LOW_MAP, but use vremap in LX version 2.
 	 */
 
 	*R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, page ) | 
-			IO_STATE(R_MMU_KSEG, seg_e, seg  ) |  /* uncached flash */
+			IO_STATE(R_MMU_KSEG, seg_e, page ) |
 			IO_STATE(R_MMU_KSEG, seg_d, page ) | 
-			IO_STATE(R_MMU_KSEG, seg_c, page ) | 
+			IO_STATE(R_MMU_KSEG, seg_c, page ) |   
 			IO_STATE(R_MMU_KSEG, seg_b, seg  ) |  /* kernel reg area */
 			IO_STATE(R_MMU_KSEG, seg_a, seg  ) |  /* Juliette etc. */
-			IO_STATE(R_MMU_KSEG, seg_9, page ) |
-			IO_STATE(R_MMU_KSEG, seg_8, page ) |
+			IO_STATE(R_MMU_KSEG, seg_9, seg  ) |  /* LED's on some boards */
+			IO_STATE(R_MMU_KSEG, seg_8, seg  ) |  /* CSE0/1, flash and I/O */
 			IO_STATE(R_MMU_KSEG, seg_7, page ) |  /* kernel vmalloc area */
 			IO_STATE(R_MMU_KSEG, seg_6, seg  ) |  /* kernel DRAM area */
 			IO_STATE(R_MMU_KSEG, seg_5, seg  ) |  /* cached flash */
@@ -307,13 +321,13 @@
 			IO_STATE(R_MMU_KSEG, seg_0, page ) ); /* user area */
 
 	*R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_e, 0x8 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_e, 0x0 ) |
 			    IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
 			    IO_FIELD(R_MMU_KBASE_HI, base_c, 0x0 ) |
 			    IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
 			    IO_FIELD(R_MMU_KBASE_HI, base_a, 0xa ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_9, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_8, 0x0 ) );
+			    IO_FIELD(R_MMU_KBASE_HI, base_9, 0x9 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_8, 0x8 ) );
 	
 	*R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
 			    IO_FIELD(R_MMU_KBASE_LO, base_6, 0x4 ) |
diff -u --recursive --new-file v2.4.3/linux/arch/cris/mm/ioremap.c linux/arch/cris/mm/ioremap.c
--- v2.4.3/linux/arch/cris/mm/ioremap.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/mm/ioremap.c	Fri Apr  6 10:42:55 2001
@@ -0,0 +1,164 @@
+/*
+ * arch/cris/mm/ioremap.c
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ * Needed for memory-mapped I/O devices mapped outside our normal DRAM
+ * window (that is, all memory-mapped I/O devices).
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ * CRIS-port by Axis Communications AB
+ */
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+	unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	if (address >= end)
+		BUG();
+	do {
+		if (!pte_none(*pte)) {
+			printk("remap_area_pte: page already exists\n");
+			BUG();
+		}
+		set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | __READABLE | 
+							     __WRITEABLE | _PAGE_GLOBAL |
+							     _PAGE_KERNEL | flags)));
+		address += PAGE_SIZE;
+		phys_addr += PAGE_SIZE;
+		pte++;
+	} while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+	unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	if (address >= end)
+		BUG();
+	do {
+		pte_t * pte = pte_alloc_kernel(pmd, address);
+		if (!pte)
+			return -ENOMEM;
+		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+				 unsigned long size, unsigned long flags)
+{
+	pgd_t * dir;
+	unsigned long end = address + size;
+
+	phys_addr -= address;
+	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
+	if (address >= end)
+		BUG();
+	do {
+		pmd_t *pmd;
+		pmd = pmd_alloc_kernel(dir, address);
+		if (!pmd)
+			return -ENOMEM;
+		if (remap_area_pmd(pmd, address, end - address,
+					 phys_addr + address, flags))
+			return -ENOMEM;
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (address && (address < end));
+	flush_tlb_all();
+	return 0;
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+	void * addr;
+	struct vm_struct * area;
+	unsigned long offset, last_addr;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+#if 0
+	/* TODO: Here we can put checks for driver-writer abuse...  */
+
+	/*
+	 * Don't remap the low PCI/ISA area, it's always mapped..
+	 */
+	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
+		return phys_to_virt(phys_addr);
+
+	/*
+	 * Don't allow anybody to remap normal RAM that we're using..
+	 */
+	if (phys_addr < virt_to_phys(high_memory)) {
+		char *t_addr, *t_end;
+		struct page *page;
+
+		t_addr = __va(phys_addr);
+		t_end = t_addr + (size - 1);
+	   
+		for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
+			if(!PageReserved(page))
+				return NULL;
+	}
+#endif
+
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr) - phys_addr;
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_vm_area(size, VM_IOREMAP);
+	if (!area)
+		return NULL;
+	addr = area->addr;
+	if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+		vfree(addr);
+		return NULL;
+	}
+	return (void *) (offset + (char *)addr);
+}
+
+void iounmap(void *addr)
+{
+	if (addr > high_memory)
+		return vfree((void *) (PAGE_MASK & (unsigned long) addr));
+}
diff -u --recursive --new-file v2.4.3/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.4.3/linux/arch/i386/Makefile	Wed Jan 10 15:06:14 2001
+++ linux/arch/i386/Makefile	Thu Apr 12 12:20:31 2001
@@ -82,6 +82,10 @@
 CFLAGS += -march=i586
 endif
 
+ifdef CONFIG_MCYRIXIII
+CFLAGS += -march=i586
+endif
+
 HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
 
 SUBDIRS += arch/i386/kernel arch/i386/mm arch/i386/lib
diff -u --recursive --new-file v2.4.3/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
--- v2.4.3/linux/arch/i386/boot/setup.S	Sat Jan 27 10:51:35 2001
+++ linux/arch/i386/boot/setup.S	Wed Apr 11 18:50:25 2001
@@ -18,7 +18,7 @@
  * March 1993/June 1994 (Christoph.Niemann@linux.org)
  *
  * add APM BIOS checking by Stephen Rothwell, May 1994
- * (Stephen.Rothwell@canb.auug.org.au)
+ * (sfr@canb.auug.org.au)
  *
  * High load stuff, initrd support and position independency
  * by Hans Lermen & Werner Almesberger, February 1996
@@ -81,14 +81,9 @@
 
 type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,
 					#      Bootlin, SYSLX, bootsect...)
-					# Else it is set by the loader:
-					# 0xTV: T=0 for LILO
-					#	T=1 for Loadlin
-					#	T=2 for bootsect-loader
-					#	T=3 for SYSLX
-					#	T=4 for ETHERBOOT
-					#       V = version
-
+					# See Documentation/i386/boot.txt for
+					# assigned ids
+	
 # flags, unused bits must be zero (RFU) bit within loadflags
 loadflags:
 LOADED_HIGH	= 1			# If set, the kernel is loaded high
diff -u --recursive --new-file v2.4.3/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.4.3/linux/arch/i386/config.in	Mon Jan  8 13:27:56 2001
+++ linux/arch/i386/config.in	Fri Apr 20 18:26:15 2001
@@ -36,24 +36,31 @@
 	 Pentium-III			CONFIG_MPENTIUMIII \
 	 Pentium-4			CONFIG_MPENTIUM4 \
 	 K6/K6-II/K6-III		CONFIG_MK6 \
-	 Athlon/K7			CONFIG_MK7 \
+	 Athlon/Duron/K7		CONFIG_MK7 \
 	 Crusoe				CONFIG_MCRUSOE \
 	 Winchip-C6			CONFIG_MWINCHIPC6 \
 	 Winchip-2			CONFIG_MWINCHIP2 \
-	 Winchip-2A/Winchip-3		CONFIG_MWINCHIP3D" Pentium-Pro
+	 Winchip-2A/Winchip-3		CONFIG_MWINCHIP3D \
+	 CyrixIII/C3			CONFIG_MCYRIXIII" Pentium-Pro
 #
 # Define implied options from the CPU selection here
 #
 
 if [ "$CONFIG_M386" = "y" ]; then
    define_bool CONFIG_X86_CMPXCHG n
+   define_bool CONFIG_X86_XADD n
    define_int  CONFIG_X86_L1_CACHE_SHIFT 4
+   define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+   define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 else
    define_bool CONFIG_X86_WP_WORKS_OK y
    define_bool CONFIG_X86_INVLPG y
    define_bool CONFIG_X86_CMPXCHG y
+   define_bool CONFIG_X86_XADD y
    define_bool CONFIG_X86_BSWAP y
    define_bool CONFIG_X86_POPAD_OK y
+   define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
+   define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
 fi
 if [ "$CONFIG_M486" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 4
@@ -111,6 +118,13 @@
    define_bool CONFIG_X86_GOOD_APIC y
    define_bool CONFIG_X86_USE_3DNOW y
    define_bool CONFIG_X86_PGE y
+   define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+fi
+if [ "$CONFIG_MCYRIXIII" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_SHIFT 5
+   define_bool CONFIG_X86_TSC y
+   define_bool CONFIG_X86_ALIGNMENT_16 y
+   define_bool CONFIG_X86_USE_3DNOW y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
 fi
 if [ "$CONFIG_MCRUSOE" = "y" ]; then
diff -u --recursive --new-file v2.4.3/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.4.3/linux/arch/i386/defconfig	Fri Mar 23 16:05:44 2001
+++ linux/arch/i386/defconfig	Tue Apr 17 17:28:02 2001
@@ -5,6 +5,8 @@
 CONFIG_ISA=y
 # CONFIG_SBUS is not set
 CONFIG_UID16=y
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -35,9 +37,11 @@
 # CONFIG_MWINCHIPC6 is not set
 # CONFIG_MWINCHIP2 is not set
 # CONFIG_MWINCHIP3D is not set
+# CONFIG_MCYRIXIII is not set
 CONFIG_X86_WP_WORKS_OK=y
 CONFIG_X86_INVLPG=y
 CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
 CONFIG_X86_BSWAP=y
 CONFIG_X86_POPAD_OK=y
 CONFIG_X86_L1_CACHE_SHIFT=5
@@ -383,6 +387,9 @@
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -561,6 +568,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
diff -u --recursive --new-file v2.4.3/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.4.3/linux/arch/i386/kernel/apm.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/i386/kernel/apm.c	Fri Apr  6 10:42:47 2001
@@ -1,6 +1,6 @@
 /* -*- linux-c -*-
  * APM BIOS driver for Linux
- * Copyright 1994-2000 Stephen Rothwell (sfr@linuxcare.com)
+ * Copyright 1994-2001 Stephen Rothwell (sfr@canb.auug.org.au)
  *
  * Initial development of this driver was funded by NEC Australia P/L
  *	and NEC Corporation
@@ -23,7 +23,7 @@
  * March 1996, Rik Faith (faith@cs.unc.edu):
  *    Prohibit APM BIOS calls unless apm_enabled.
  *    (Thanks to Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>)
- * April 1996, Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
+ * April 1996, Stephen Rothwell (sfr@canb.auug.org.au)
  *    Version 1.0 and 1.1
  * May 1996, Version 1.2
  * Feb 1998, Version 1.3
@@ -119,7 +119,7 @@
  *         Make power off under SMP work again.
  *         Fix thinko with initial engaging of BIOS.
  *         Make sure power off only happens on CPU 0
- *         (Paul "Rusty" Russell <rusty@linuxcare.com>).
+ *         (Paul "Rusty" Russell <rusty@rustcorp.com.au>).
  *         Do error notification to user mode if BIOS calls fail.
  *         Move entrypoint offset fix to ...boot/setup.S
  *         where it belongs (Cosmos <gis88564@cis.nctu.edu.tw>).
@@ -227,6 +227,8 @@
  * P: Toshiba 1950S: battery life information only gets updated after resume
  * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking
  * 	broken in BIOS [Reported by Garst R. Reese <reese@isn.net>]
+ * ?: AcerNote-950: oops on reading /proc/apm - workaround is a WIP
+ * 	Neale Banks <neale@lowendale.com.au> December 2000
  *
  * Legend: U = unusable with APM patches
  *         P = partially usable with APM patches
@@ -1550,6 +1552,9 @@
 			apm_disabled = 1;
 		if (strncmp(str, "on", 2) == 0)
 			apm_disabled = 0;
+		if ((strncmp(str, "broken-psr", 10) == 0) ||
+		    (strncmp(str, "broken_psr", 10) == 0))
+			apm_info.get_power_status_broken = 1;
 		invert = (strncmp(str, "no-", 3) == 0);
 		if (invert)
 			str += 3;
diff -u --recursive --new-file v2.4.3/linux/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c
--- v2.4.3/linux/arch/i386/kernel/bluesmoke.c	Fri Dec 29 14:07:20 2000
+++ linux/arch/i386/kernel/bluesmoke.c	Wed Apr 11 19:02:27 2001
@@ -45,6 +45,7 @@
 				printk(" at %08x%08x", 
 					high, low);
 			}
+			printk("\n");
 			/* Clear it */
 			wrmsr(0x401+i*4, 0UL, 0UL);
 			/* Serialize */
diff -u --recursive --new-file v2.4.3/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v2.4.3/linux/arch/i386/kernel/head.S	Sun Mar 25 17:38:31 2001
+++ linux/arch/i386/kernel/head.S	Fri Apr 20 16:23:30 2001
@@ -169,9 +169,7 @@
 	rep
 	movsl
 1:
-#ifdef CONFIG_SMP
 checkCPUtype:
-#endif
 
 	movl $-1,X86_CPUID		#  -1 for no CPUID initially
 
@@ -244,9 +242,7 @@
 	orl $2,%eax		# set MP
 2:	movl %eax,%cr0
 	call check_x87
-#ifdef CONFIG_SMP
 	incb ready
-#endif
 	lgdt gdt_descr
 	lidt idt_descr
 	ljmp $(__KERNEL_CS),$1f
@@ -278,9 +274,7 @@
 	jmp L6			# main should never return here, but
 				# just in case, we know what happens.
 
-#ifdef CONFIG_SMP
 ready:	.byte 0
-#endif
 
 /*
  * We depend on ET to be correct. This checks for 287/387.
diff -u --recursive --new-file v2.4.3/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.4.3/linux/arch/i386/kernel/i386_ksyms.c	Fri Mar  2 12:03:49 2001
+++ linux/arch/i386/kernel/i386_ksyms.c	Wed Apr 25 13:31:03 2001
@@ -61,7 +61,6 @@
 EXPORT_SYMBOL(dump_extended_fpu);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(__io_virt_debug);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(disable_irq_nosync);
@@ -73,13 +72,14 @@
 EXPORT_SYMBOL(apm_info);
 EXPORT_SYMBOL(gdt);
 
+#ifdef CONFIG_IO_DEBUG
+EXPORT_SYMBOL(__io_virt_debug);
+#endif
+
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
-EXPORT_SYMBOL_NOVERS(__down_write_failed);
-EXPORT_SYMBOL_NOVERS(__down_read_failed);
-EXPORT_SYMBOL_NOVERS(__rwsem_wake);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy_generic);
 /* Delay loops */
@@ -97,6 +97,7 @@
 EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(simple_strtol);
+EXPORT_SYMBOL(strstr);
 
 EXPORT_SYMBOL(strncpy_from_user);
 EXPORT_SYMBOL(__strncpy_from_user);
diff -u --recursive --new-file v2.4.3/linux/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c
--- v2.4.3/linux/arch/i386/kernel/ldt.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/i386/kernel/ldt.c	Wed Apr 11 19:05:37 2001
@@ -94,8 +94,6 @@
 			goto out_unlock;
 		memset(mm->context.segments, 0, LDT_ENTRIES*LDT_ENTRY_SIZE);
 		
-		if (atomic_read(&mm->mm_users) > 1)
-			printk(KERN_WARNING "LDT allocated for cloned task!\n");
 		/*
 		 * Possibly do an SMP cross-call to other CPUs to reload
 		 * their LDTs?
diff -u --recursive --new-file v2.4.3/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.4.3/linux/arch/i386/kernel/mtrr.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/i386/kernel/mtrr.c	Wed Apr 11 19:02:27 2001
@@ -231,6 +231,20 @@
   v1.37
     20001109   H. Peter Anvin <hpa@zytor.com>
 	       Use the new centralized CPU feature detects.
+
+  v1.38
+    20010309   Dave Jones <davej@suse.de>
+	       Add support for Cyrix III.
+
+  v1.39
+    20010312   Dave Jones <davej@suse.de>
+               Ugh, I broke AMD support.
+	       Reworked fix by Troels Walsted Hansen <troels@thule.no>
+
+  v1.40
+    20010327   Dave Jones <davej@suse.de>
+	       Adapted Cyrix III support to include VIA C3.
+
 */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -250,6 +264,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #define MTRR_NEED_STRINGS
 #include <asm/mtrr.h>
 #include <linux/init.h>
@@ -269,7 +284,7 @@
 #include <asm/hardirq.h>
 #include <linux/irq.h>
 
-#define MTRR_VERSION            "1.37 (20001109)"
+#define MTRR_VERSION            "1.40 (20010327)"
 
 #define TRUE  1
 #define FALSE 0
@@ -464,6 +479,27 @@
 static int have_wrcomb (void)
 {
     unsigned long config, dummy;
+    struct pci_dev *dev = NULL;
+    
+   /* ServerWorks LE chipsets have problems with  write-combining 
+      Don't allow it and  leave room for other chipsets to be tagged */
+
+    if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) != NULL) {
+	switch(dev->vendor) {
+        case PCI_VENDOR_ID_SERVERWORKS:
+ 	    switch (dev->device) {
+	    case PCI_DEVICE_ID_SERVERWORKS_LE:
+		return 0;
+		break;
+	    default:
+		break;
+	    }
+	    break;
+	default:
+	    break;
+	}
+    }
+
 
     switch ( mtrr_if )
     {
@@ -538,7 +574,7 @@
      * Note: shift==0xf means 4G, this is unsupported.
      */
     if (shift)
-      *size = (reg < 7 ? 0x1UL : 0x40UL) << shift;
+      *size = (reg < 7 ? 0x1UL : 0x40UL) << (shift - 1);
     else
       *size = 0;
 
@@ -1777,7 +1813,8 @@
     }
     devfs_set_file_size (devfs_handle, ascii_buf_bytes);
 #  ifdef CONFIG_PROC_FS
-    proc_root_mtrr->size = ascii_buf_bytes;
+    if (proc_root_mtrr)
+	proc_root_mtrr->size = ascii_buf_bytes;
 #  endif  /*  CONFIG_PROC_FS  */
 }   /*  End Function compute_ascii  */
 
@@ -1938,6 +1975,7 @@
 	get_mtrr = intel_get_mtrr;
 	set_mtrr_up = intel_set_mtrr_up;
 	switch (boot_cpu_data.x86_vendor) {
+
 	case X86_VENDOR_AMD:
 		/* The original Athlon docs said that
 		   total addressable memory is 44 bits wide.
@@ -1956,12 +1994,27 @@
 			size_and_mask = ~size_or_mask & 0xfff00000;
 			break;
 		}
+		size_or_mask  = 0xff000000; /* 36 bits */
+		size_and_mask = 0x00f00000;
+		break;
+
+	case X86_VENDOR_CENTAUR:
+		/* Cyrix III has Intel style MTRRs, but doesn't support PAE */
+		if (boot_cpu_data.x86 == 6 &&
+			(boot_cpu_data.x86_model == 6 ||
+			 boot_cpu_data.x86_model == 7)) {
+			size_or_mask  = 0xfff00000; /* 32 bits */
+			size_and_mask = 0;
+		}
+		break;
+
 	default:
 		/* Intel, etc. */
 		size_or_mask  = 0xff000000; /* 36 bits */
 		size_and_mask = 0x00f00000;
 		break;
 	}
+
     } else if ( test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ) {
 	/* Pre-Athlon (K6) AMD CPU MTRRs */
 	mtrr_if = MTRR_IF_AMD_K6;
@@ -2072,8 +2125,10 @@
 
 #ifdef CONFIG_PROC_FS
     proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
-    proc_root_mtrr->owner = THIS_MODULE;
-    proc_root_mtrr->proc_fops = &mtrr_fops;
+    if (proc_root_mtrr) {
+	proc_root_mtrr->owner = THIS_MODULE;
+	proc_root_mtrr->proc_fops = &mtrr_fops;
+    }
 #endif
 #ifdef CONFIG_DEVFS_FS
     devfs_handle = devfs_register (NULL, "cpu/mtrr", DEVFS_FL_DEFAULT, 0, 0,
diff -u --recursive --new-file v2.4.3/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.4.3/linux/arch/i386/kernel/pci-pc.c	Thu Mar 29 11:24:17 2001
+++ linux/arch/i386/kernel/pci-pc.c	Thu Apr 19 22:57:06 2001
@@ -843,6 +843,8 @@
 	pcibios_last_bus = -1;
 }
 
+#if 0
+/* Until we get proper handling pray the BIOS gets it right */
 /*
  * ServerWorks host bridges -- Find and scan all secondary buses.
  * Register 0x44 contains first, 0x45 last bus number routed there.
@@ -860,6 +862,7 @@
 		printk("PCI: ServerWorks host bridge: last bus %02x\n", pcibios_last_bus);
 	}
 }
+#endif
 
 #if 0
 /* Our bus code shouldnt need this fixup any more. Delete once verified */
@@ -957,34 +960,6 @@
 	d->irq = 9;
 }
 
-static void __init pci_fixup_vt8363(struct pci_dev *d)
-{
-	/*
-	 * The VIA bridge will corrupt disks without these settings.
-	 */
-	u8 tmp;
-	pci_read_config_byte(d, 0x54, &tmp);
-	if(tmp & (1<<2)) {
-		printk("PCI: Bus master Pipeline request disabled\n");
-		pci_write_config_byte(d, 0x54, tmp & ~(1<<2));
-	}
-	pci_read_config_byte(d, 0x70, &tmp);
-	if(tmp & (1<<3)) {
-		printk("PCI: Disabled enhanced CPU to PCI writes\n");
-		pci_write_config_byte(d, 0x70, tmp & ~(1<<3));
-	}
-	pci_read_config_byte(d, 0x71, &tmp);
-	if((tmp & (1<<3)) == 0) {
-		printk("PCI: Bursting cornercase bug worked around\n");
-		pci_write_config_byte(d, 0x71, tmp | (1<<3));
-	}
-	pci_read_config_byte(d, 0x76, &tmp);
-	if(tmp & (1<<7)) {
-		printk("PCI: Post Write Fail set to Retry\n");
-		pci_write_config_byte(d, 0x76, tmp & ~(1<<7));
-	}
-}
-
 static void __init pci_fixup_via691(struct pci_dev *d)
 {
 	/*
@@ -1033,7 +1008,6 @@
 	{ 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_8363_0,	pci_fixup_vt8363 },
  	{ 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 },
diff -u --recursive --new-file v2.4.3/linux/arch/i386/kernel/semaphore.c linux/arch/i386/kernel/semaphore.c
--- v2.4.3/linux/arch/i386/kernel/semaphore.c	Sat Nov 18 17:31:25 2000
+++ linux/arch/i386/kernel/semaphore.c	Thu Apr 12 12:22:53 2001
@@ -14,7 +14,6 @@
  */
 #include <linux/config.h>
 #include <linux/sched.h>
-
 #include <asm/semaphore.h>
 
 /*
@@ -179,6 +178,7 @@
  * value..
  */
 asm(
+".text\n"
 ".align 4\n"
 ".globl __down_failed\n"
 "__down_failed:\n\t"
@@ -193,6 +193,7 @@
 );
 
 asm(
+".text\n"
 ".align 4\n"
 ".globl __down_failed_interruptible\n"
 "__down_failed_interruptible:\n\t"
@@ -205,6 +206,7 @@
 );
 
 asm(
+".text\n"
 ".align 4\n"
 ".globl __down_failed_trylock\n"
 "__down_failed_trylock:\n\t"
@@ -217,6 +219,7 @@
 );
 
 asm(
+".text\n"
 ".align 4\n"
 ".globl __up_wakeup\n"
 "__up_wakeup:\n\t"
@@ -230,199 +233,9 @@
 	"ret"
 );
 
-asm(
-"
-.align 4
-.globl __down_read_failed
-__down_read_failed:
-	pushl	%edx
-	pushl	%ecx
-	jnc	2f
-
-3:	call	down_read_failed_biased
-
-1:	popl	%ecx
-	popl	%edx
-	ret
-
-2:	call	down_read_failed
-	" LOCK "subl	$1,(%eax)
-	jns	1b
-	jnc	2b
-	jmp	3b
-"
-);
-
-asm(
-"
-.align 4
-.globl __down_write_failed
-__down_write_failed:
-	pushl	%edx
-	pushl	%ecx
-	jnc	2f
-
-3:	call	down_write_failed_biased
-
-1:	popl	%ecx
-	popl	%edx
-	ret
-
-2:	call	down_write_failed
-	" LOCK "subl	$" RW_LOCK_BIAS_STR ",(%eax)
-	jz	1b
-	jnc	2b
-	jmp	3b
-"
-);
-
-struct rw_semaphore *FASTCALL(rwsem_wake_readers(struct rw_semaphore *sem));
-struct rw_semaphore *FASTCALL(rwsem_wake_writer(struct rw_semaphore *sem));
-
-struct rw_semaphore *FASTCALL(down_read_failed_biased(struct rw_semaphore *sem));
-struct rw_semaphore *FASTCALL(down_write_failed_biased(struct rw_semaphore *sem));
-struct rw_semaphore *FASTCALL(down_read_failed(struct rw_semaphore *sem));
-struct rw_semaphore *FASTCALL(down_write_failed(struct rw_semaphore *sem));
-
-struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->read_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);	/* put ourselves at the end of the list */
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (atomic_read(&sem->count) >= 0)
-		wake_up(&sem->wait);
-
-	return sem;
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-struct rw_semaphore *down_read_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	__up_read(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-struct rw_semaphore *down_write_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	__up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-asm(
-"
-.align 4
-.globl __rwsem_wake
-__rwsem_wake:
-	pushl	%edx
-	pushl	%ecx
-
-	jz	1f
-	call	rwsem_wake_readers
-	jmp	2f
-
-1:	call	rwsem_wake_writer
-
-2:	popl	%ecx
-	popl	%edx
-	ret
-"
-);
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
+/*
+ * rw spinlock fallbacks
  */
-struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->read_bias_granted, 1))
-		BUG();
-	wake_up(&sem->wait);
-	return sem;
-}
-
-struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->write_bias_granted, 1))
-		BUG();
-	wake_up(&sem->write_bias_wait);
-	return sem;
-}
-
 #if defined(CONFIG_SMP)
 asm(
 "
@@ -451,4 +264,3 @@
 "
 );
 #endif
-
diff -u --recursive --new-file v2.4.3/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.4.3/linux/arch/i386/kernel/setup.c	Sun Mar 25 18:24:31 2001
+++ linux/arch/i386/kernel/setup.c	Fri Apr  6 10:42:55 2001
@@ -58,6 +58,12 @@
  *  Massive cleanup of CPU detection and bug handling;
  *  Transmeta CPU detection,
  *  H. Peter Anvin <hpa@zytor.com>, November 2000
+ *
+ *  Added E820 sanitization routine (removes overlapping memory regions);
+ *  Brian Moyle <bmoyle@mvista.com>, February 2001
+ *
+ *  VIA C3 Support.
+ *  Dave Jones <davej@suse.de>, March 2001
  */
 
 /*
@@ -440,6 +446,170 @@
 }
 
 /*
+ * Sanitize the BIOS e820 map.
+ *
+ * Some e820 responses include overlapping entries.  The following 
+ * replaces the original e820 map with a new one, removing overlaps.
+ *
+ */
+static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
+{
+	struct change_member {
+		struct e820entry *pbios; /* pointer to original bios entry */
+		unsigned long long addr; /* address for this change point */
+	};
+	struct change_member change_point_list[2*E820MAX];
+	struct change_member *change_point[2*E820MAX];
+	struct e820entry *overlap_list[E820MAX];
+	struct e820entry new_bios[E820MAX];
+	struct change_member *change_tmp;
+	unsigned long current_type, last_type;
+	unsigned long long last_addr;
+	int chgidx, still_changing;
+	int overlap_entries;
+	int new_bios_entry;
+	int old_nr, new_nr;
+	int i;
+
+	/*
+		Visually we're performing the following (1,2,3,4 = memory types)...
+
+		Sample memory map (w/overlaps):
+		   ____22__________________
+		   ______________________4_
+		   ____1111________________
+		   _44_____________________
+		   11111111________________
+		   ____________________33__
+		   ___________44___________
+		   __________33333_________
+		   ______________22________
+		   ___________________2222_
+		   _________111111111______
+		   _____________________11_
+		   _________________4______
+
+		Sanitized equivalent (no overlap):
+		   1_______________________
+		   _44_____________________
+		   ___1____________________
+		   ____22__________________
+		   ______11________________
+		   _________1______________
+		   __________3_____________
+		   ___________44___________
+		   _____________33_________
+		   _______________2________
+		   ________________1_______
+		   _________________4______
+		   ___________________2____
+		   ____________________33__
+		   ______________________4_
+	*/
+
+	/* if there's only one memory region, don't bother */
+	if (*pnr_map < 2)
+		return -1;
+
+	old_nr = *pnr_map;
+
+	/* bail out if we find any unreasonable addresses in bios map */
+	for (i=0; i<old_nr; i++)
+		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
+			return -1;
+
+	/* create pointers for initial change-point information (for sorting) */
+	for (i=0; i < 2*old_nr; i++)
+		change_point[i] = &change_point_list[i];
+
+	/* record all known change-points (starting and ending addresses) */
+	chgidx = 0;
+	for (i=0; i < old_nr; i++)	{
+		change_point[chgidx]->addr = biosmap[i].addr;
+		change_point[chgidx++]->pbios = &biosmap[i];
+		change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
+		change_point[chgidx++]->pbios = &biosmap[i];
+	}
+
+	/* sort change-point list by memory addresses (low -> high) */
+	still_changing = 1;
+	while (still_changing)	{
+		still_changing = 0;
+		for (i=1; i < 2*old_nr; i++)  {
+			/* if <current_addr> > <last_addr>, swap */
+			/* or, if current=<start_addr> & last=<end_addr>, swap */
+			if ((change_point[i]->addr < change_point[i-1]->addr) ||
+				((change_point[i]->addr == change_point[i-1]->addr) &&
+				 (change_point[i]->addr == change_point[i]->pbios->addr) &&
+				 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
+			   )
+			{
+				change_tmp = change_point[i];
+				change_point[i] = change_point[i-1];
+				change_point[i-1] = change_tmp;
+				still_changing=1;
+			}
+		}
+	}
+
+	/* create a new bios memory map, removing overlaps */
+	overlap_entries=0;	 /* number of entries in the overlap table */
+	new_bios_entry=0;	 /* index for creating new bios map entries */
+	last_type = 0;		 /* start with undefined memory type */
+	last_addr = 0;		 /* start with 0 as last starting address */
+	/* loop through change-points, determining affect on the new bios map */
+	for (chgidx=0; chgidx < 2*old_nr; chgidx++)
+	{
+		/* keep track of all overlapping bios entries */
+		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
+		{
+			/* add map entry to overlap list (> 1 entry implies an overlap) */
+			overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
+		}
+		else
+		{
+			/* remove entry from list (order independent, so swap with last) */
+			for (i=0; i<overlap_entries; i++)
+			{
+				if (overlap_list[i] == change_point[chgidx]->pbios)
+					overlap_list[i] = overlap_list[overlap_entries-1];
+			}
+			overlap_entries--;
+		}
+		/* if there are overlapping entries, decide which "type" to use */
+		/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
+		current_type = 0;
+		for (i=0; i<overlap_entries; i++)
+			if (overlap_list[i]->type > current_type)
+				current_type = overlap_list[i]->type;
+		/* continue building up new bios map based on this information */
+		if (current_type != last_type)	{
+			if (last_type != 0)	 {
+				new_bios[new_bios_entry].size =
+					change_point[chgidx]->addr - last_addr;
+				/* move forward only if the new size was non-zero */
+				if (new_bios[new_bios_entry].size != 0)
+					if (++new_bios_entry >= E820MAX)
+						break; 	/* no more space left for new bios entries */
+			}
+			if (current_type != 0)	{
+				new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
+				new_bios[new_bios_entry].type = current_type;
+				last_addr=change_point[chgidx]->addr;
+			}
+			last_type = current_type;
+		}
+	}
+	new_nr = new_bios_entry;   /* retain count for new bios entries */
+
+	/* copy new bios mapping into original location */
+	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
+	*pnr_map = new_nr;
+
+	return 0;
+}
+
+/*
  * Copy the BIOS e820 map into a safe place.
  *
  * Sanity-check it while we're at it..
@@ -506,6 +676,7 @@
 	 * Otherwise fake a memory map; one section from 0k->640k,
 	 * the next section from 1mb->appropriate_mem_k
 	 */
+	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
 	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
 		unsigned long mem_size;
 
@@ -560,7 +731,7 @@
 				 * blow away any automatically generated
 				 * size
 				 */
-				unsigned long start_at, mem_size;
+				unsigned long long start_at, mem_size;
  
 				if (usermem == 0) {
 					/* first time in: zap the whitelist
@@ -1401,7 +1572,7 @@
 
 		case 6:
 			switch (c->x86_model) {
-				case 6:	/* Cyrix III */
+				case 6 ... 7:		/* Cyrix III or C3 */
 					rdmsr (0x1107, lo, hi);
 					lo |= (1<<1 | 1<<7);	/* Report CX8 & enable PGE */
 					wrmsr (0x1107, lo, hi);
@@ -1481,6 +1652,32 @@
 	wrmsr(0x80860004, cap_mask, uk);
 }
 
+
+static void __init init_rise(struct cpuinfo_x86 *c)
+{
+	printk("CPU: Rise iDragon");
+	if (c->x86_model > 2)
+		printk(" II");
+	printk("\n");
+	printk("If you have one of these please email davej@suse.de\n");
+
+	/* Unhide possibly hidden capability flags
+	   The mp6 iDragon family don't have MSRs.
+	   We switch on extra features with this cpuid wierdness: */
+	__asm__ (
+		"movl $0x6363452a, %%eax\n\t"
+		"movl $0x3231206c, %%ecx\n\t"
+		"movl $0x2a32313a, %%edx\n\t"
+		"cpuid\n\t"
+		"movl $0x63634523, %%eax\n\t"
+		"movl $0x32315f6c, %%ecx\n\t"
+		"movl $0x2333313a, %%edx\n\t"
+		"cpuid\n\t" : : : "eax", "ebx", "ecx", "edx"
+	);
+	set_bit(X86_FEATURE_CX8, &c->x86_capability);
+}
+
+
 extern void trap_init_f00f_bug(void);
 
 static void __init init_intel(struct cpuinfo_x86 *c)
@@ -1732,8 +1929,8 @@
 	  { "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	    NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
 	{ X86_VENDOR_RISE,	5,
-	  { "mP6", "mP6", NULL, NULL, NULL, NULL, NULL,
-	    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
+	  { "iDragon", NULL, "iDragon", NULL, NULL, NULL, NULL,
+	    NULL, "iDragon II", "iDragon II", NULL, NULL, NULL, NULL, NULL, NULL }},
 };
 
 /* Look up CPU names by table lookup. */
@@ -1997,6 +2194,15 @@
 	case X86_VENDOR_UNKNOWN:
 	default:
 		/* Not much we can do here... */
+		/* Check if at least it has cpuid */
+		if (c->cpuid_level == -1)
+		{
+			/* No cpuid. It must be an ancient CPU */
+			if (c->x86 == 4)
+				strcpy(c->x86_model_id, "486");
+			else if (c->x86 == 3)
+				strcpy(c->x86_model_id, "386");
+		}
 		break;
 
 	case X86_VENDOR_CYRIX:
@@ -2021,6 +2227,10 @@
 
 	case X86_VENDOR_TRANSMETA:
 		init_transmeta(c);
+		break;
+
+	case X86_VENDOR_RISE:
+		init_rise(c);
 		break;
 	}
 	
diff -u --recursive --new-file v2.4.3/linux/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile
--- v2.4.3/linux/arch/i386/lib/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/i386/lib/Makefile	Wed Apr 25 13:31:03 2001
@@ -8,8 +8,8 @@
 L_TARGET = lib.a
 
 obj-y = checksum.o old-checksum.o delay.o \
-	usercopy.o getuser.o putuser.o iodebug.o \
-	memcpy.o
+	usercopy.o getuser.o putuser.o \
+	memcpy.o strstr.o
 
 obj-$(CONFIG_X86_USE_3DNOW) += mmx.o
 obj-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff -u --recursive --new-file v2.4.3/linux/arch/i386/lib/mmx.c linux/arch/i386/lib/mmx.c
--- v2.4.3/linux/arch/i386/lib/mmx.c	Thu Mar  1 18:04:34 2001
+++ linux/arch/i386/lib/mmx.c	Wed Apr 11 19:02:27 2001
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/sched.h>
@@ -5,6 +6,7 @@
 #include <asm/i387.h>
 #include <asm/hardirq.h> 
 
+
 /*
  *	MMX 3DNow! library helper functions
  *
@@ -95,6 +97,13 @@
 	return p;
 }
 
+#ifdef CONFIG_MK7
+
+/*
+ *	The K7 has streaming cache bypass load/store. The Cyrix III, K6 and
+ *	other MMX using processors do not.
+ */
+
 static void fast_clear_page(void *page)
 {
 	int i;
@@ -194,6 +203,118 @@
 	);
 	kernel_fpu_end();
 }
+
+#else
+
+/*
+ *	Generic MMX implementation without K7 specific streaming
+ */
+ 
+static void fast_clear_page(void *page)
+{
+	int i;
+	if (!(current->flags & PF_USEDFPU))
+		clts();
+	else
+	{
+		__asm__ __volatile__ ( " fnsave %0; fwait\n"::"m"(current->thread.i387));
+		current->flags &= ~PF_USEDFPU;
+	}
+	
+	__asm__ __volatile__ (
+		"  pxor %%mm0, %%mm0\n" : :
+	);
+
+	for(i=0;i<4096/128;i++)
+	{
+		__asm__ __volatile__ (
+		"  movq %%mm0, (%0)\n"
+		"  movq %%mm0, 8(%0)\n"
+		"  movq %%mm0, 16(%0)\n"
+		"  movq %%mm0, 24(%0)\n"
+		"  movq %%mm0, 32(%0)\n"
+		"  movq %%mm0, 40(%0)\n"
+		"  movq %%mm0, 48(%0)\n"
+		"  movq %%mm0, 56(%0)\n"
+		"  movq %%mm0, 64(%0)\n"
+		"  movq %%mm0, 72(%0)\n"
+		"  movq %%mm0, 80(%0)\n"
+		"  movq %%mm0, 88(%0)\n"
+		"  movq %%mm0, 96(%0)\n"
+		"  movq %%mm0, 104(%0)\n"
+		"  movq %%mm0, 112(%0)\n"
+		"  movq %%mm0, 120(%0)\n"
+		: : "r" (page) : "memory");
+		page+=128;
+	}
+	stts();
+}
+
+static void fast_copy_page(void *to, void *from)
+{
+	int i;
+	if (!(current->flags & PF_USEDFPU))
+		clts();
+	else
+	{
+		__asm__ __volatile__ ( " fnsave %0; fwait\n"::"m"(current->thread.i387));
+		current->flags &= ~PF_USEDFPU;
+	}
+
+	__asm__ __volatile__ (
+		"1: prefetch (%0)\n"
+		"   prefetch 64(%0)\n"
+		"   prefetch 128(%0)\n"
+		"   prefetch 192(%0)\n"
+		"   prefetch 256(%0)\n"
+		"2:  \n"
+		".section .fixup, \"ax\"\n"
+		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
+		"   jmp 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 1b, 3b\n"
+		".previous"
+		: : "r" (from) );
+
+	for(i=0; i<4096/64; i++)
+	{
+		__asm__ __volatile__ (
+		"1: prefetch 320(%0)\n"
+		"2: movq (%0), %%mm0\n"
+		"   movq 8(%0), %%mm1\n"
+		"   movq 16(%0), %%mm2\n"
+		"   movq 24(%0), %%mm3\n"
+		"   movq %%mm0, (%1)\n"
+		"   movq %%mm1, 8(%1)\n"
+		"   movq %%mm2, 16(%1)\n"
+		"   movq %%mm3, 24(%1)\n"
+		"   movq 32(%0), %%mm0\n"
+		"   movq 40(%0), %%mm1\n"
+		"   movq 48(%0), %%mm2\n"
+		"   movq 56(%0), %%mm3\n"
+		"   movq %%mm0, 32(%1)\n"
+		"   movq %%mm1, 40(%1)\n"
+		"   movq %%mm2, 48(%1)\n"
+		"   movq %%mm3, 56(%1)\n"
+		".section .fixup, \"ax\"\n"
+		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
+		"   jmp 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 1b, 3b\n"
+		".previous"
+		: : "r" (from), "r" (to) : "memory");
+		from+=64;
+		to+=64;
+	}
+	stts();
+}
+
+
+#endif
 
 /*
  *	Favour MMX for page clear and copy. 
diff -u --recursive --new-file v2.4.3/linux/arch/i386/lib/strstr.c linux/arch/i386/lib/strstr.c
--- v2.4.3/linux/arch/i386/lib/strstr.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/lib/strstr.c	Fri Apr  6 10:42:47 2001
@@ -0,0 +1,31 @@
+#include <linux/string.h>
+
+char * strstr(const char * cs,const char * ct)
+{
+int	d0, d1;
+register char * __res;
+__asm__ __volatile__(
+	"movl %6,%%edi\n\t"
+	"repne\n\t"
+	"scasb\n\t"
+	"notl %%ecx\n\t"
+	"decl %%ecx\n\t"	/* NOTE! This also sets Z if searchstring='' */
+	"movl %%ecx,%%edx\n"
+	"1:\tmovl %6,%%edi\n\t"
+	"movl %%esi,%%eax\n\t"
+	"movl %%edx,%%ecx\n\t"
+	"repe\n\t"
+	"cmpsb\n\t"
+	"je 2f\n\t"		/* also works for empty string, see above */
+	"xchgl %%eax,%%esi\n\t"
+	"incl %%esi\n\t"
+	"cmpb $0,-1(%%eax)\n\t"
+	"jne 1b\n\t"
+	"xorl %%eax,%%eax\n\t"
+	"2:"
+	:"=a" (__res), "=&c" (d0), "=&S" (d1)
+	:"0" (0), "1" (0xffffffff), "2" (cs), "g" (ct)
+	:"dx", "di");
+return __res;
+}
+
diff -u --recursive --new-file v2.4.3/linux/arch/i386/lib/usercopy.c linux/arch/i386/lib/usercopy.c
--- v2.4.3/linux/arch/i386/lib/usercopy.c	Fri Nov 12 04:29:47 1999
+++ linux/arch/i386/lib/usercopy.c	Fri Apr 13 20:26:07 2001
@@ -34,6 +34,8 @@
 		else
 			mmx_copy_user_zeroing(to, from, n);
 	}
+	else
+		memset(to, 0, n);
 	return n;
 }
 
@@ -52,6 +54,8 @@
 {
 	if (access_ok(VERIFY_READ, from, n))
 		__copy_user_zeroing(to,from,n);
+	else
+		memset(to, 0, n);
 	return n;
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/control_w.h linux/arch/i386/math-emu/control_w.h
--- v2.4.3/linux/arch/i386/math-emu/control_w.h	Thu Jun 29 08:25:27 1995
+++ linux/arch/i386/math-emu/control_w.h	Fri Apr  6 10:42:47 2001
@@ -42,4 +42,4 @@
 /* FULL_PRECISION simulates all exceptions masked */
 #define FULL_PRECISION  (PR_64_BITS | RC_RND | 0x3f)
 
-#endif _CONTROLW_H_
+#endif /* _CONTROLW_H_ */
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/div_Xsig.S linux/arch/i386/math-emu/div_Xsig.S
--- v2.4.3/linux/arch/i386/math-emu/div_Xsig.S	Fri Aug 27 10:18:17 1999
+++ linux/arch/i386/math-emu/div_Xsig.S	Fri Apr  6 10:42:47 2001
@@ -70,7 +70,7 @@
 	.long	0
 FPU_result_1:
 	.long	0
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
 
 .text
@@ -79,7 +79,7 @@
 	movl	%esp,%ebp
 #ifndef NON_REENTRANT_FPU
 	subl	$28,%esp
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 	pushl	%esi
 	pushl	%edi
@@ -91,7 +91,7 @@
 #ifdef PARANOID
 	testl	$0x80000000, XsigH(%ebx)	/* Divisor */
 	je	L_bugged
-#endif PARANOID
+#endif /* PARANOID */
 
 
 /*---------------------------------------------------------------------------+
@@ -164,7 +164,7 @@
 
 #ifdef PARANOID
 	jb	L_bugged_1
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	/* need to subtract another once of the denom */
 	incl	FPU_result_3	/* Correct the answer */
@@ -177,7 +177,7 @@
 #ifdef PARANOID
 	sbbl	$0,FPU_accum_3
 	jne	L_bugged_1	/* Must check for non-zero result here */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 /*----------------------------------------------------------------------*/
 /* Half of the main problem is done, there is just a reduced numerator
@@ -207,7 +207,7 @@
 
 #ifdef PARANOID
 	je	L_bugged_2	/* Can't bump the result to 1.0 */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LDo_2nd_div:
 	cmpl	$0,%ecx		/* augmented denom msw */
@@ -230,7 +230,7 @@
 
 #ifdef PARANOID
 	jc	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */
 
 	movl	FPU_result_2,%eax	/* Get the result back */
 	mull	XsigL(%ebx)	/* now mul the ls dw of the denom */
@@ -241,14 +241,14 @@
 
 #ifdef PARANOID
 	jc	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */
 
 	jz	LDo_3rd_32_bits
 
 #ifdef PARANOID
 	cmpl	$1,FPU_accum_2
 	jne	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	/* need to subtract another once of the denom */
 	movl	XsigL(%ebx),%eax
@@ -260,14 +260,14 @@
 #ifdef PARANOID
 	jc	L_bugged_2
 	jne	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	addl	$1,FPU_result_2	/* Correct the answer */
 	adcl	$0,FPU_result_3
 
 #ifdef PARANOID
 	jc	L_bugged_2	/* Must check for non-zero result here */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 /*----------------------------------------------------------------------*/
 /* The division is essentially finished here, we just need to perform
@@ -362,4 +362,4 @@
 	call	EXCEPTION
 	pop	%ebx
 	jmp	L_exit
-#endif PARANOID
+#endif /* PARANOID */ 
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/errors.c linux/arch/i386/math-emu/errors.c
--- v2.4.3/linux/arch/i386/math-emu/errors.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/errors.c	Fri Apr  6 10:42:47 2001
@@ -141,7 +141,7 @@
 if ( partial_status & SW_Zero_Div )    printk("SW: divide by zero\n");
 if ( partial_status & SW_Denorm_Op )   printk("SW: denormalized operand\n");
 if ( partial_status & SW_Invalid )     printk("SW: invalid operation\n");
-#endif DEBUGGING
+#endif /* DEBUGGING */
 
   printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n",
 	 partial_status & 0x8000 ? 1 : 0,   /* busy */
@@ -327,7 +327,7 @@
 #ifdef PRINT_MESSAGES
       /* My message from the sponsor */
       printk(FPU_VERSION" "__DATE__" (C) W. Metzenthen.\n");
-#endif PRINT_MESSAGES
+#endif /* PRINT_MESSAGES */
       
       /* Get a name string for error reporting */
       for (i=0; exception_names[i].type; i++)
@@ -338,7 +338,7 @@
 	{
 #ifdef PRINT_MESSAGES
 	  printk("FP Exception: %s!\n", exception_names[i].name);
-#endif PRINT_MESSAGES
+#endif /* PRINT_MESSAGES */
 	}
       else
 	printk("FPU emulator: Unknown Exception: 0x%04x!\n", n);
@@ -351,7 +351,7 @@
 #ifdef PRINT_MESSAGES
       else
 	FPU_printall();
-#endif PRINT_MESSAGES
+#endif /* PRINT_MESSAGES */
 
       /*
        * The 80486 generates an interrupt on the next non-control FPU
@@ -363,7 +363,7 @@
 
 #ifdef __DEBUG__
   math_abort(FPU_info,SIGFPE);
-#endif __DEBUG__
+#endif /* __DEBUG__ */
 
 }
 
@@ -469,7 +469,7 @@
   else
 #ifdef PARANOID
     if (tagb == TW_NaN)
-#endif PARANOID
+#endif /* PARANOID */
     {
       signalling = !(b->sigh & 0x40000000);
       x = b;
@@ -481,7 +481,7 @@
       EXCEPTION(EX_INTERNAL|0x113);
       x = &CONST_QNaN;
     }
-#endif PARANOID
+#endif /* PARANOID */
 
   if ( (!signalling) || (control_word & CW_Invalid) )
     {
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/exception.h linux/arch/i386/math-emu/exception.h
--- v2.4.3/linux/arch/i386/math-emu/exception.h	Mon Dec 11 13:34:33 2000
+++ linux/arch/i386/math-emu/exception.h	Fri Apr  6 10:42:47 2001
@@ -18,7 +18,7 @@
 
 #ifndef SW_C1
 #include "fpu_emu.h"
-#endif SW_C1
+#endif /* SW_C1 */
 
 #define FPU_BUSY        Const_(0x8000)   /* FPU busy bit (8087 compatibility) */
 #define EX_ErrorSummary Const_(0x0080)   /* Error summary status */
@@ -48,6 +48,6 @@
 #define	EXCEPTION(x)	FPU_exception(x)
 #endif
 
-#endif __ASSEMBLY__
+#endif /* __ASSEMBLY__ */ 
 
-#endif _EXCEPTION_H_
+#endif /* _EXCEPTION_H_ */
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/fpu_asm.h linux/arch/i386/math-emu/fpu_asm.h
--- v2.4.3/linux/arch/i386/math-emu/fpu_asm.h	Mon Dec 11 13:34:33 2000
+++ linux/arch/i386/math-emu/fpu_asm.h	Fri Apr  6 10:42:47 2001
@@ -29,4 +29,4 @@
 #define	SIGL(x)	SIGL_OFFSET##(x)
 #define	SIGH(x)	4(x)
 
-#endif _FPU_ASM_H_
+#endif /* _FPU_ASM_H_ */
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/fpu_emu.h linux/arch/i386/math-emu/fpu_emu.h
--- v2.4.3/linux/arch/i386/math-emu/fpu_emu.h	Mon Dec 11 13:34:33 2000
+++ linux/arch/i386/math-emu/fpu_emu.h	Fri Apr  6 10:42:47 2001
@@ -88,7 +88,7 @@
 #else
 #  define RE_ENTRANT_CHECK_OFF
 #  define RE_ENTRANT_CHECK_ON
-#endif RE_ENTRANT_CHECKING
+#endif /* RE_ENTRANT_CHECKING */
 
 #define FWAIT_OPCODE 0x9b
 #define OP_SIZE_PREFIX 0x66
@@ -212,6 +212,6 @@
 #include "fpu_proto.h"
 #endif
 
-#endif __ASSEMBLY__
+#endif /* __ASSEMBLY__ */
 
-#endif _FPU_EMU_H_
+#endif /* _FPU_EMU_H_ */
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/fpu_entry.c linux/arch/i386/math-emu/fpu_entry.c
--- v2.4.3/linux/arch/i386/math-emu/fpu_entry.c	Mon Jun 19 18:10:44 2000
+++ linux/arch/i386/math-emu/fpu_entry.c	Fri Apr  6 10:42:47 2001
@@ -78,7 +78,7 @@
   fdivr_,   FPU_trigb,  __BAD__, __BAD__, fdiv_i,  __BAD__, fdivp_,  __BAD__,
 };
 
-#endif NO_UNDOC_CODE
+#endif /* NO_UNDOC_CODE */
 
 
 #define _NONE_ 0   /* Take no special action */
@@ -120,12 +120,12 @@
   _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
 };
 
-#endif NO_UNDOC_CODE
+#endif /* NO_UNDOC_CODE */
 
 
 #ifdef RE_ENTRANT_CHECKING
 u_char emulating=0;
-#endif RE_ENTRANT_CHECKING
+#endif /* RE_ENTRANT_CHECKING */
 
 static int valid_prefix(u_char *Byte, u_char **fpu_eip,
 			overrides *override);
@@ -152,7 +152,7 @@
       printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
     }
   RE_ENTRANT_CHECK_ON;
-#endif RE_ENTRANT_CHECKING
+#endif /* RE_ENTRANT_CHECKING */
 
   if (!current->used_math)
     {
@@ -251,7 +251,7 @@
 #ifdef PARANOID
       EXCEPTION(EX_INTERNAL|0x128);
       math_abort(FPU_info,SIGILL);
-#endif PARANOID
+#endif /* PARANOID */
     }
 
   RE_ENTRANT_CHECK_OFF;
@@ -386,7 +386,7 @@
 			/* fdiv or fsub */
 			real_2op_NaN(&loaded_data, loaded_tag, 0, &loaded_data);
 		      else
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */ 
 			/* fadd, fdivr, fmul, or fsubr */
 			real_2op_NaN(&loaded_data, loaded_tag, 0, st0_ptr);
 		    }
@@ -497,7 +497,7 @@
 	 to do this: */
       operand_address.offset = 0;
       operand_address.selector = FPU_DS;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 
       st0_ptr = &st(0);
       st0_tag = FPU_gettag0();
@@ -557,7 +557,7 @@
   RE_ENTRANT_CHECK_OFF;
   FPU_printall();
   RE_ENTRANT_CHECK_ON;
-#endif DEBUG
+#endif /* DEBUG */
 
   if (FPU_lookahead && !current->need_resched)
     {
@@ -669,7 +669,7 @@
 	__asm__("movl %0,%%esp ; ret": :"g" (((long) info)-4));
 #ifdef PARANOID
       printk("ERROR: wm-FPU-emu math_abort failed!\n");
-#endif PARANOID
+#endif /* PARANOID */
 }
 
 
@@ -739,7 +739,7 @@
   S387->twd |= 0xffff0000;
   S387->fcs &= ~0xf8000000;
   S387->fos |= 0xffff0000;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
   __copy_to_user(d, &S387->cwd, 7*4);
   RE_ENTRANT_CHECK_ON;
 
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/fpu_etc.c linux/arch/i386/math-emu/fpu_etc.c
--- v2.4.3/linux/arch/i386/math-emu/fpu_etc.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/fpu_etc.c	Fri Apr  6 10:42:47 2001
@@ -68,7 +68,7 @@
 	      /* This is weird! */
 	      if (getsign(st0_ptr) == SIGN_POS)
 		setcc(SW_C3);
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 	      return;
 	    }
 	  break;
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/fpu_trig.c linux/arch/i386/math-emu/fpu_trig.c
--- v2.4.3/linux/arch/i386/math-emu/fpu_trig.c	Thu Nov  4 09:10:22 1999
+++ linux/arch/i386/math-emu/fpu_trig.c	Fri Apr  6 10:42:47 2001
@@ -98,7 +98,7 @@
 	      q++;
 	    }
 	}
-#endif BETTER_THAN_486
+#endif /* BETTER_THAN_486 */
     }
 #ifdef BETTER_THAN_486
   else
@@ -138,7 +138,7 @@
 	    }
 	}
     }
-#endif BETTER_THAN_486
+#endif /* BETTER_THAN_486 */
 
   FPU_settag0(st0_tag);
   control_word = old_cw;
@@ -186,7 +186,7 @@
 #ifdef PARANOID
   else
     EXCEPTION(EX_INTERNAL|0x0112);
-#endif PARANOID
+#endif /* PARANOID */
 }
 
 
@@ -232,7 +232,7 @@
 #ifdef PARANOID
     default:
       EXCEPTION(EX_INTERNAL|0x0112);
-#endif PARANOID
+#endif /* PARANOID */
     }
 }
 
@@ -463,7 +463,7 @@
 #ifdef PARANOID
   else
     EXCEPTION(EX_INTERNAL | 0x119);
-#endif PARANOID
+#endif /* PARANOID */
 }
 
 
@@ -716,7 +716,7 @@
 	  set_precision_flag_down();  /* 80486 appears to do this. */
 #else
 	  set_precision_flag_up();  /* Must be up. */
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 	  return 0;
 	}
     }
@@ -1008,7 +1008,7 @@
 	      setcc(SW_C2);
 #else
 	      setcc(0);
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 	      return;
 	    }
 	  cc = SW_C2;
@@ -1114,7 +1114,7 @@
 #ifdef PARANOID
   if ( (st0_tag != TW_NaN) && (st1_tag != TW_NaN) )
       EXCEPTION(EX_INTERNAL | 0x118);
-#endif PARANOID
+#endif /* PARANOID */
 
   real_2op_NaN(st1_ptr, st1_tag, 0, st1_ptr);
 
@@ -1315,7 +1315,7 @@
 	  sign = getsign(st1_ptr);
 	  if ( FPU_divide_by_zero(1, sign) < 0 )
 	    return;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 
 	  changesign(st1_ptr);
 	}
@@ -1451,7 +1451,7 @@
 #ifdef PARANOID
   else
     EXCEPTION(EX_INTERNAL | 0x125);
-#endif PARANOID
+#endif /* PARANOID */
 
   FPU_pop();
   set_precision_flag_up();  /* We do not really know if up or down */
@@ -1542,7 +1542,7 @@
 #ifdef PARANOID
 	  EXCEPTION(EX_INTERNAL | 0x116);
 	  return;
-#endif PARANOID
+#endif /* PARANOID */
 	}
     }
   else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
@@ -1560,7 +1560,7 @@
 #else
 		  if ( arith_invalid(1) < 0 )
 		    return;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 		}
 	      else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
 		return;
@@ -1583,7 +1583,7 @@
 		  changesign(st1_ptr);
 #else
 		  if ( arith_invalid(1) < 0 ) return;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 		}
 	      else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
 		return;
@@ -1618,14 +1618,14 @@
 	  /* This should have higher priority than denormals, but... */
 	  if ( arith_invalid(1) < 0 )  /* log(-infinity) */
 	    return;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 	  if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
 	    return;
 #ifdef PECULIAR_486
 	  /* Denormal operands actually get higher priority */
 	  if ( arith_invalid(1) < 0 )  /* log(-infinity) */
 	    return;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 	}
       else if ( st1_tag == TAG_Zero )
 	{
@@ -1654,7 +1654,7 @@
       EXCEPTION(EX_INTERNAL | 0x117);
       return;
     }
-#endif PARANOID
+#endif /* PARANOID */
 
   FPU_pop();
   return;
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/get_address.c linux/arch/i386/math-emu/get_address.c
--- v2.4.3/linux/arch/i386/math-emu/get_address.c	Mon Jun 19 12:56:08 2000
+++ linux/arch/i386/math-emu/get_address.c	Fri Apr  6 10:42:47 2001
@@ -143,7 +143,7 @@
       EXCEPTION(EX_INTERNAL|0x130);
       math_abort(FPU_info,SIGSEGV);
     }
-#endif PARANOID
+#endif /* PARANOID */
   addr->selector = VM86_REG_(segment);
   return (unsigned long)VM86_REG_(segment) << 4;
 }
@@ -166,7 +166,7 @@
       EXCEPTION(EX_INTERNAL|0x132);
       math_abort(FPU_info,SIGSEGV);
     }
-#endif PARANOID
+#endif /* PARANOID */
 
   switch ( segment )
     {
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/load_store.c linux/arch/i386/math-emu/load_store.c
--- v2.4.3/linux/arch/i386/math-emu/load_store.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/load_store.c	Fri Apr  6 10:42:47 2001
@@ -85,7 +85,7 @@
 #ifdef PARANOID
       else
 	EXCEPTION(EX_INTERNAL|0x140);
-#endif PARANOID
+#endif /* PARANOID */
     }
 
   switch ( type_table[type] )
@@ -112,7 +112,7 @@
     default:
       EXCEPTION(EX_INTERNAL|0x141);
       return 0;
-#endif PARANOID
+#endif /* PARANOID */
     }
 
   switch ( type )
@@ -217,7 +217,7 @@
 	partial_status &= ~(SW_Summary | SW_Backward);
 #ifdef PECULIAR_486
       control_word |= 0x40;  /* An 80486 appears to always set this bit */
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
       return 1;
     case 025:      /* fld m80real */
       clear_C1();
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/poly.h linux/arch/i386/math-emu/poly.h
--- v2.4.3/linux/arch/i386/math-emu/poly.h	Thu Nov  4 09:10:22 1999
+++ linux/arch/i386/math-emu/poly.h	Fri Apr  6 10:42:47 2001
@@ -118,4 +118,4 @@
                :"=g" (*x):"g" (x):"si","ax","cx");
 }
 
-#endif _POLY_H
+#endif /* _POLY_H */
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/poly_2xm1.c linux/arch/i386/math-emu/poly_2xm1.c
--- v2.4.3/linux/arch/i386/math-emu/poly_2xm1.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/poly_2xm1.c	Fri Apr  6 10:42:47 2001
@@ -67,7 +67,7 @@
       EXCEPTION(EX_INTERNAL|0x127);
       return 1;
     }
-#endif PARANOID
+#endif /* PARANOID */
 
   argSignif.lsw = 0;
   XSIG_LL(argSignif) = Xll = significand(arg);
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/poly_atan.c linux/arch/i386/math-emu/poly_atan.c
--- v2.4.3/linux/arch/i386/math-emu/poly_atan.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/poly_atan.c	Fri Apr  6 10:42:47 2001
@@ -124,7 +124,7 @@
 	      EXCEPTION(EX_INTERNAL|0x104);  /* There must be a logic error */
 	      return;
 	    }
-#endif PARANOID
+#endif /* PARANOID */
 	  argSignif.msw = 0;   /* Make the transformed arg -> 0.0 */
 	}
       else
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/poly_l2.c linux/arch/i386/math-emu/poly_l2.c
--- v2.4.3/linux/arch/i386/math-emu/poly_l2.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/poly_l2.c	Fri Apr  6 10:42:47 2001
@@ -157,7 +157,7 @@
 #else
 	  if ( arith_invalid(1) < 0 )
 	    return 1;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 	}
 
       /* 80486 appears to do this */
@@ -243,7 +243,7 @@
 	  /* The argument is too large */
 	}
     }
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 
   arg_signif.lsw = argSignif.lsw; XSIG_LL(arg_signif) = XSIG_LL(argSignif);
   adj = norm_Xsig(&argSignif);
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/poly_sin.c linux/arch/i386/math-emu/poly_sin.c
--- v2.4.3/linux/arch/i386/math-emu/poly_sin.c	Thu Nov  4 09:10:22 1999
+++ linux/arch/i386/math-emu/poly_sin.c	Fri Apr  6 10:42:47 2001
@@ -199,7 +199,7 @@
     {
       EXCEPTION(EX_INTERNAL|0x150);
     }
-#endif PARANOID
+#endif /* PARANOID */
 
 }
 
@@ -224,7 +224,7 @@
       FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
       return;
     }
-#endif PARANOID
+#endif /* PARANOID */
 
   exponent = exponent(st0_ptr);
 
@@ -392,6 +392,6 @@
     {
       EXCEPTION(EX_INTERNAL|0x151);
     }
-#endif PARANOID
+#endif /* PARANOID */
 
 }
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/poly_tan.c linux/arch/i386/math-emu/poly_tan.c
--- v2.4.3/linux/arch/i386/math-emu/poly_tan.c	Wed Jul  5 10:56:13 2000
+++ linux/arch/i386/math-emu/poly_tan.c	Fri Apr  6 10:42:47 2001
@@ -66,7 +66,7 @@
 #ifdef PARANOID
   if ( signnegative(st0_ptr) )	/* Can't hack a number < 0.0 */
     { arith_invalid(0); return; }  /* Need a positive number */
-#endif PARANOID
+#endif /* PARANOID */
 
   /* Split the problem into two domains, smaller and larger than pi/4 */
   if ( (exponent == 0) || ((exponent == -1) && (st0_ptr->sigh > 0xc90fdaa2)) )
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_compare.c linux/arch/i386/math-emu/reg_compare.c
--- v2.4.3/linux/arch/i386/math-emu/reg_compare.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/reg_compare.c	Fri Apr  6 10:42:47 2001
@@ -136,7 +136,7 @@
 #ifdef PARANOID
   if (!(st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
   if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
-#endif PARANOID
+#endif /* PARANOID */
 
   diff = exp0 - expb;
   if ( diff == 0 )
@@ -203,7 +203,7 @@
 	EXCEPTION(EX_INTERNAL|0x121);
 	f = SW_C3 | SW_C2 | SW_C0;
 	break;
-#endif PARANOID
+#endif /* PARANOID */
       }
   setcc(f);
   if (c & COMP_Denormal)
@@ -255,7 +255,7 @@
 	EXCEPTION(EX_INTERNAL|0x122);
 	f = SW_C3 | SW_C2 | SW_C0;
 	break;
-#endif PARANOID
+#endif /* PARANOID */
       }
   setcc(f);
   if (c & COMP_Denormal)
@@ -312,7 +312,7 @@
 	EXCEPTION(EX_INTERNAL|0x123);
 	f = SW_C3 | SW_C2 | SW_C0;
 	break;
-#endif PARANOID
+#endif /* PARANOID */ 
       }
   setcc(f);
   if (c & COMP_Denormal)
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_constant.h linux/arch/i386/math-emu/reg_constant.h
--- v2.4.3/linux/arch/i386/math-emu/reg_constant.h	Mon Dec 11 13:34:34 2000
+++ linux/arch/i386/math-emu/reg_constant.h	Fri Apr  6 10:42:47 2001
@@ -28,4 +28,4 @@
 extern FPU_REG const CONST_MINF;
 extern FPU_REG const CONST_QNaN;
 
-#endif _REG_CONSTANT_H_
+#endif /* _REG_CONSTANT_H_ */
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_divide.c linux/arch/i386/math-emu/reg_divide.c
--- v2.4.3/linux/arch/i386/math-emu/reg_divide.c	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/reg_divide.c	Fri Apr  6 10:42:47 2001
@@ -201,6 +201,6 @@
       EXCEPTION(EX_INTERNAL|0x102);
       return FPU_Exception;
     }
-#endif PARANOID
+#endif /* PARANOID */ 
 
 }
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_ld_str.c linux/arch/i386/math-emu/reg_ld_str.c
--- v2.4.3/linux/arch/i386/math-emu/reg_ld_str.c	Sun Jan 25 11:01:48 1998
+++ linux/arch/i386/math-emu/reg_ld_str.c	Fri Apr  6 10:42:47 2001
@@ -439,7 +439,7 @@
 		 converts to decide underflow. */
 	      if ( !((tmp.sigh == 0x00100000) && (tmp.sigl == 0) &&
 		  (st0_ptr->sigl & 0x000007ff)) )
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 		{
 		  EXCEPTION(EX_Underflow);
 		  /* This is a special case: see sec 16.2.5.1 of
@@ -559,7 +559,7 @@
 	  /* Underflow has priority. */
 	  if ( control_word & CW_Underflow )
 	    denormal_operand();
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 	  reg_copy(st0_ptr, &tmp);
 	  goto denormal_arg;
 	}
@@ -659,7 +659,7 @@
 		 converts to decide underflow. */
 	      if ( !((tmp.sigl == 0x00800000) &&
 		  ((st0_ptr->sigh & 0x000000ff) || st0_ptr->sigl)) )
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 		{
 		  EXCEPTION(EX_Underflow);
 		  /* This is a special case: see sec 16.2.5.1 of
@@ -776,7 +776,7 @@
 	  /* Underflow has priority. */
 	  if ( control_word & CW_Underflow )
 	    denormal_operand();
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */ 
 	  goto denormal_arg;
 	}
       else if (st0_tag == TW_Infinity)
@@ -1221,7 +1221,7 @@
 
 #ifdef PECULIAR_486
   control_word &= ~0xe080;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */ 
 
   top = (partial_status >> SW_Top_Shift) & 7;
 
@@ -1303,7 +1303,7 @@
       FPU_put_user(control_word & ~0xe080, (unsigned long *) d);
 #else
       FPU_put_user(control_word, (unsigned short *) d);
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
       FPU_put_user(status_word(), (unsigned short *) (d+2));
       FPU_put_user(fpu_tag_word, (unsigned short *) (d+4));
       FPU_put_user(instruction_address.offset, (unsigned short *) (d+6));
@@ -1335,7 +1335,7 @@
       fpu_tag_word |= 0xffff0000;
       I387.soft.fcs &= ~0xf8000000;
       I387.soft.fos |= 0xffff0000;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
       __copy_to_user(d, &control_word, 7*4);
       RE_ENTRANT_CHECK_ON;
       d += 0x1c;
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_mul.c linux/arch/i386/math-emu/reg_mul.c
--- v2.4.3/linux/arch/i386/math-emu/reg_mul.c	Wed Jun 24 14:30:08 1998
+++ linux/arch/i386/math-emu/reg_mul.c	Fri Apr  6 10:42:47 2001
@@ -126,6 +126,6 @@
       EXCEPTION(EX_INTERNAL|0x102);
       return FPU_Exception;
     }
-#endif PARANOID
+#endif /* PARANOID */ 
 
 }
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_round.S linux/arch/i386/math-emu/reg_round.S
--- v2.4.3/linux/arch/i386/math-emu/reg_round.S	Thu Nov  4 09:10:22 1999
+++ linux/arch/i386/math-emu/reg_round.S	Fri Apr  6 10:42:47 2001
@@ -100,7 +100,7 @@
 	.byte	0
 FPU_denormal:
 	.byte	0
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
 
 .text
@@ -126,13 +126,13 @@
 
 #ifndef NON_REENTRANT_FPU
 	pushl	%ebx		/* adjust the stack pointer */
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 #ifdef PARANOID
 /* Cannot use this here yet */
 /*	orl	%eax,%eax */
 /*	jns	L_entry_bugged */
-#endif PARANOID
+#endif /* PARANOID */
 
 	cmpw	EXP_UNDER,EXP(%edi)
 	jle	L_Make_denorm			/* The number is a de-normal */
@@ -160,12 +160,12 @@
 	je	LRound_To_64
 #ifdef PARANOID
 	jmp	L_bugged_denorm_486
-#endif PARANOID
+#endif /* PARANOID */ 
 #else
 #ifdef PARANOID
 	jmp	L_bugged_denorm	/* There is no bug, just a bad control word */
-#endif PARANOID
-#endif PECULIAR_486
+#endif /* PARANOID */ 
+#endif /* PECULIAR_486 */
 
 
 /* Round etc to 24 bit precision */
@@ -186,7 +186,7 @@
 
 #ifdef PARANOID
 	jmp	L_bugged_round24
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LUp_24:
 	cmpb	SIGN_POS,PARAM5
@@ -266,7 +266,7 @@
 
 #ifdef PARANOID
 	jmp	L_bugged_round53
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LUp_53:
 	cmpb	SIGN_POS,PARAM5
@@ -340,7 +340,7 @@
 
 #ifdef PARANOID
 	jmp	L_bugged_round64
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LUp_64:
 	cmpb	SIGN_POS,PARAM5
@@ -430,7 +430,7 @@
 
 #ifndef NON_REENTRANT_FPU
 	popl	%ebx		/* adjust the stack pointer */
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 fpu_Arith_exit:
 	popl	%ebx
@@ -570,7 +570,7 @@
 	/* But check it... just in case. */
 	cmpw	EXP_UNDER+1,EXP(%edi)
 	jne	L_norm_bugged
-#endif PARANOID
+#endif /* PARANOID */
 
 #ifdef PECULIAR_486
 	/*
@@ -586,7 +586,7 @@
 #else
 	orl	%eax,%eax		/* ms bits */
 	js	L_Normalised		/* No longer a denormal */
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */ 
 
 	jnz	LDenormal_adj_exponent
 
@@ -673,7 +673,7 @@
 	call	EXCEPTION
 	popl	%ebx
 	jmp	L_exception_exit
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */ 
 
 L_bugged_round24:
 	pushl	EX_INTERNAL|0x231
@@ -706,4 +706,4 @@
 L_exception_exit:
 	mov	$-1,%eax
 	jmp	fpu_reg_round_special_exit
-#endif PARANOID
+#endif /* PARANOID */ 
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_u_add.S linux/arch/i386/math-emu/reg_u_add.S
--- v2.4.3/linux/arch/i386/math-emu/reg_u_add.S	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/reg_u_add.S	Fri Apr  6 10:42:47 2001
@@ -72,7 +72,7 @@
 
 	testl	$0x80000000,SIGH(%esi)
 	je	L_bugged
-#endif PARANOID
+#endif /* PARANOID */
 
 /* The number to be shifted is in %eax:%ebx:%edx */
 	cmpw	$32,%cx		/* shrd only works for 0..31 bits */
@@ -164,4 +164,4 @@
 	popl	%esi
 	leave
 	ret
-#endif PARANOID
+#endif /* PARANOID */
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_u_div.S linux/arch/i386/math-emu/reg_u_div.S
--- v2.4.3/linux/arch/i386/math-emu/reg_u_div.S	Fri Aug 27 10:18:17 1999
+++ linux/arch/i386/math-emu/reg_u_div.S	Fri Apr  6 10:42:47 2001
@@ -67,7 +67,7 @@
 	.long	0
 FPU_ovfl_flag:
 	.byte	0
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
 #define REGA	PARAM1
 #define REGB	PARAM2
@@ -79,7 +79,7 @@
 	movl	%esp,%ebp
 #ifndef NON_REENTRANT_FPU
 	subl	$28,%esp
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
 	pushl	%esi
 	pushl	%edi
@@ -112,7 +112,7 @@
 /*	je	L_bugged */
 	testl	$0x80000000, SIGH(%ebx)	/* Divisor */
 	je	L_bugged
-#endif PARANOID
+#endif /* PARANOID */ 
 
 /* Check if the divisor can be treated as having just 32 bits */
 	cmpl	$0,SIGL(%ebx)
@@ -248,7 +248,7 @@
 
 #ifdef PARANOID
 	jb	L_bugged_1
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	/* need to subtract another once of the denom */
 	incl	FPU_result_2	/* Correct the answer */
@@ -261,7 +261,7 @@
 #ifdef PARANOID
 	sbbl	$0,FPU_accum_3
 	jne	L_bugged_1	/* Must check for non-zero result here */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 /*----------------------------------------------------------------------*/
 /* Half of the main problem is done, there is just a reduced numerator
@@ -291,7 +291,7 @@
 
 #ifdef PARANOID
 	je	L_bugged_2	/* Can't bump the result to 1.0 */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LDo_2nd_div:
 	cmpl	$0,%ecx		/* augmented denom msw */
@@ -314,7 +314,7 @@
 
 #ifdef PARANOID
 	jc	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	movl	FPU_result_1,%eax	/* Get the result back */
 	mull	SIGL(%ebx)	/* now mul the ls dw of the denom */
@@ -325,14 +325,14 @@
 
 #ifdef PARANOID
 	jc	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	jz	LDo_3rd_32_bits
 
 #ifdef PARANOID
 	cmpl	$1,FPU_accum_2
 	jne	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */
 
 	/* need to subtract another once of the denom */
 	movl	SIGL(%ebx),%eax
@@ -344,14 +344,14 @@
 #ifdef PARANOID
 	jc	L_bugged_2
 	jne	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	addl	$1,FPU_result_1	/* Correct the answer */
 	adcl	$0,FPU_result_2
 
 #ifdef PARANOID
 	jc	L_bugged_2	/* Must check for non-zero result here */
-#endif PARANOID
+#endif /* PARANOID */
 
 /*----------------------------------------------------------------------*/
 /* The division is essentially finished here, we just need to perform
@@ -470,4 +470,4 @@
 
 	leave
 	ret
-#endif PARANOID
+#endif /* PARANOID */ 
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_u_mul.S linux/arch/i386/math-emu/reg_u_mul.S
--- v2.4.3/linux/arch/i386/math-emu/reg_u_mul.S	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/reg_u_mul.S	Fri Apr  6 10:42:47 2001
@@ -40,7 +40,7 @@
 	.long	0
 FPU_accum_1:
 	.long	0
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
 
 .text
@@ -49,7 +49,7 @@
 	movl	%esp,%ebp
 #ifndef NON_REENTRANT_FPU
 	subl	$8,%esp
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 	pushl	%esi
 	pushl	%edi
@@ -63,7 +63,7 @@
 	jz	L_bugged
 	testl	$0x80000000,SIGH(%edi)
 	jz	L_bugged
-#endif PARANOID
+#endif /* PARANOID */
 
 	xorl	%ecx,%ecx
 	xorl	%ebx,%ebx
@@ -144,5 +144,5 @@
 	popl	%esi
 	leave
 	ret
-#endif PARANOID
+#endif /* PARANOID */ 
 
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/reg_u_sub.S linux/arch/i386/math-emu/reg_u_sub.S
--- v2.4.3/linux/arch/i386/math-emu/reg_u_sub.S	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/reg_u_sub.S	Fri Apr  6 10:42:47 2001
@@ -54,7 +54,7 @@
 
 	testl	$0x80000000,SIGH(%esi)
 	je	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */
 
 /*--------------------------------------+
  |	Form a register holding the     |
@@ -165,7 +165,7 @@
 #ifdef PARANOID
 	/* We can never get a borrow */
 	jc	L_bugged
-#endif PARANOID
+#endif /* PARANOID */
 
 /*--------------------------------------+
  |	Normalize the result		|
@@ -199,7 +199,7 @@
 #ifdef PARANOID
 	orl	%edx,%edx
 	jnz	L_bugged_3
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	/* The result is zero */
 	movw	$0,EXP(%edi)		/* exponent */
@@ -262,7 +262,7 @@
 L_error_exit:
 	movl	$-1,%eax
 
-#endif PARANOID
+#endif /* PARANOID */
 
 L_exit:
 	popl	%ebx
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/status_w.h linux/arch/i386/math-emu/status_w.h
--- v2.4.3/linux/arch/i386/math-emu/status_w.h	Mon Dec 11 13:34:33 2000
+++ linux/arch/i386/math-emu/status_w.h	Fri Apr  6 10:42:47 2001
@@ -58,8 +58,8 @@
 #  define clear_C1()  { partial_status &= ~SW_C1; }
 # else
 #  define clear_C1()
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 
-#endif __ASSEMBLY__
+#endif /* __ASSEMBLY__ */
 
-#endif _STATUS_H_
+#endif /* _STATUS_H_ */
diff -u --recursive --new-file v2.4.3/linux/arch/i386/math-emu/wm_sqrt.S linux/arch/i386/math-emu/wm_sqrt.S
--- v2.4.3/linux/arch/i386/math-emu/wm_sqrt.S	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/wm_sqrt.S	Fri Apr  6 10:42:47 2001
@@ -70,7 +70,7 @@
 	.long	0
 FPU_fsqrt_arg_0:
 	.long	0		/* ls word, at most the ms bit is set */
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 
 .text
@@ -79,7 +79,7 @@
 	movl	%esp,%ebp
 #ifndef NON_REENTRANT_FPU
 	subl	$28,%esp
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 	pushl	%esi
 	pushl	%edi
 	pushl	%ebx
@@ -210,7 +210,7 @@
 /* It should be possible to get here only if the arg is ffff....ffff */
 	cmp	$0xffffffff,FPU_fsqrt_arg_1
 	jnz	sqrt_stage_2_error
-#endif PARANOID
+#endif /* PARANOID */
 
 /* The best rounded result. */
 	xorl	%eax,%eax
@@ -224,7 +224,7 @@
 sqrt_stage_2_error:
 	pushl	EX_INTERNAL|0x213
 	call	EXCEPTION
-#endif PARANOID
+#endif /* PARANOID */ 
 
 sqrt_stage_2_done:
 
@@ -279,7 +279,7 @@
 	call	EXCEPTION
 
 sqrt_stage_3_no_error:
-#endif PARANOID
+#endif /* PARANOID */
 
 	movl	FPU_accum_2,%edx
 	movl	FPU_accum_1,%eax
@@ -385,7 +385,7 @@
 	call	EXCEPTION
 
 sqrt_near_exact_ok:
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	or	%ebx,%ebx
 	js	sqrt_near_exact_small
@@ -445,7 +445,7 @@
 	call	EXCEPTION
 
 sqrt_more_prec_ok:
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	or	%ebx,%ebx
 	js	sqrt_more_prec_small
diff -u --recursive --new-file v2.4.3/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.4.3/linux/arch/i386/mm/init.c	Mon Mar 26 11:01:56 2001
+++ linux/arch/i386/mm/init.c	Fri Apr 20 16:15:20 2001
@@ -309,14 +309,11 @@
 	 * Zap initial low-memory mappings.
 	 *
 	 * Note that "pgd_clear()" doesn't do it for
-	 * us in this case, because pgd_clear() is a
-	 * no-op in the 2-level case (pmd_clear() is
-	 * the thing that clears the page-tables in
-	 * that case).
+	 * us, because pgd_clear() is a no-op on i386.
 	 */
 	for (i = 0; i < USER_PTRS_PER_PGD; i++)
 #if CONFIG_X86_PAE
-		pgd_clear(swapper_pg_dir+i);
+		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
 #else
 		set_pgd(swapper_pg_dir+i, __pgd(0));
 #endif
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/Makefile linux/arch/ia64/Makefile
--- v2.4.3/linux/arch/ia64/Makefile	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/Makefile	Thu Apr  5 12:51:46 2001
@@ -5,7 +5,7 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1998-2000 by David Mosberger-Tang <davidm@hpl.hp.com>
+# Copyright (C) 1998-2001 by David Mosberger-Tang <davidm@hpl.hp.com>
 #
 
 NM := $(CROSS_COMPILE)nm -B
@@ -14,13 +14,13 @@
 export AWK
 
 LINKFLAGS = -static -T arch/$(ARCH)/vmlinux.lds
-AFLAGS += -Wa,-x 
+AFLAGS += -Wa,-x
 AFLAGS_KERNEL := -mconstant-gp
 EXTRA	=
 
 CFLAGS := $(CFLAGS) -pipe $(EXTRA) -Wa,-x -ffixed-r13 -mfixed-range=f10-f15,f32-f127 \
 	  -funwind-tables -falign-functions=32
-# -frename-registers
+# -frename-registers (this crashes the Nov 17 compiler...)
 CFLAGS_KERNEL := -mconstant-gp
 
 ifeq ($(CONFIG_ITANIUM_ASTEP_SPECIFIC),y)
@@ -53,7 +53,7 @@
 endif
 
 ifdef CONFIG_IA64_SGI_SN1
-CFLAGS += -DBRINGUP
+	CFLAGS		+= -DBRINGUP
         SUBDIRS         :=      arch/$(ARCH)/sn/sn1	\
 				arch/$(ARCH)/sn		\
 				arch/$(ARCH)/sn/io	\
@@ -103,6 +103,11 @@
 
 FORCE: ;
 
+compressed: vmlinux
+	$(OBJCOPY) --strip-all vmlinux vmlinux-tmp
+	gzip -9 vmlinux-tmp
+	mv vmlinux-tmp.gz vmlinux.gz
+
 rawboot:
 	@$(MAKEBOOT) rawboot
 
@@ -120,8 +125,6 @@
 	@$(MAKEBOOT) srmboot
 
 archclean:
-	@$(MAKE) -C arch/$(ARCH)/kernel clean
-	@$(MAKE) -C arch/$(ARCH)/tools clean
 	@$(MAKEBOOT) clean
 
 archmrproper:
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/boot/bootloader.c linux/arch/ia64/boot/bootloader.c
--- v2.4.3/linux/arch/ia64/boot/bootloader.c	Mon Oct  9 17:54:53 2000
+++ linux/arch/ia64/boot/bootloader.c	Thu Apr  5 12:51:47 2001
@@ -3,8 +3,8 @@
  *
  * Loads an ELF kernel.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
  *
  * 01/07/99 S.Eranian modified to pass command line arguments to kernel
@@ -65,35 +65,22 @@
 	}
 }
 
-void
-enter_virtual_mode (unsigned long new_psr)
-{
-	long tmp;
-
-	asm volatile ("movl %0=1f" : "=r"(tmp));
-	asm volatile ("mov cr.ipsr=%0" :: "r"(new_psr));
-	asm volatile ("mov cr.iip=%0" :: "r"(tmp));
-	asm volatile ("mov cr.ifs=r0");
-	asm volatile ("rfi;;");
-	asm volatile ("1:");
-}
-
 #define MAX_ARGS 32
 
 void
 _start (void)
 {
-	register long sp asm ("sp");
 	static char stack[16384] __attribute__ ((aligned (16)));
 	static char mem[4096];
 	static char buffer[1024];
-	unsigned long flags, off;
+	unsigned long off;
 	int fd, i;
 	struct disk_req req;
 	struct disk_stat stat;
 	struct elfhdr *elf;
 	struct elf_phdr *elf_phdr;	/* program header */
 	unsigned long e_entry, e_phoff, e_phnum;
+	register struct ia64_boot_param *bp;
 	char *kpath, *args;
 	long arglen = 0;
 
@@ -107,15 +94,13 @@
 	ssc(0, 0, 0, 0, SSC_CONSOLE_INIT);
 
 	/*
-	 * S.Eranian: extract the commandline argument from the 
-	 * simulator
+	 * S.Eranian: extract the commandline argument from the simulator
 	 *
 	 * The expected format is as follows:
          *
 	 *	kernelname args...
 	 *
-	 * Both are optional but you can't have the second one without the 
-	 * first.
+	 * Both are optional but you can't have the second one without the first.
 	 */
 	arglen = ssc((long) buffer, 0, 0, 0, SSC_GET_ARGS);
 
@@ -183,6 +168,10 @@
 		e_phoff += sizeof(*elf_phdr);
 
 		elf_phdr = (struct elf_phdr *) mem;
+
+		if (elf_phdr->p_type != PT_LOAD)
+			continue;
+
 		req.len = elf_phdr->p_filesz;
 		req.addr = __pa(elf_phdr->p_vaddr);
 		ssc(fd, 1, (long) &req, elf_phdr->p_offset, SSC_READ);
@@ -197,38 +186,12 @@
 	/* fake an I/O base address: */
 	asm volatile ("mov ar.k0=%0" :: "r"(0xffffc000000UL));
 
-	/*
-	 * Install a translation register that identity maps the
-	 * kernel's 256MB page.
-	 */
-	ia64_clear_ic(flags);
-	ia64_set_rr(          0, (0x1000 << 8) | (_PAGE_SIZE_1M << 2));
-	ia64_set_rr(PAGE_OFFSET, (ia64_rid(0, PAGE_OFFSET) << 8) | (_PAGE_SIZE_256M << 2));
-	ia64_srlz_d();
-	ia64_itr(0x3, 0, 1024*1024,
-		 pte_val(mk_pte_phys(1024*1024, __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX))),
-		 _PAGE_SIZE_1M);
-	ia64_itr(0x3, 1, PAGE_OFFSET,
-		 pte_val(mk_pte_phys(0, __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX))),
-		 _PAGE_SIZE_256M);
-	ia64_srlz_i();
-
-	enter_virtual_mode(flags | IA64_PSR_IT | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT
-			   | IA64_PSR_DFH | IA64_PSR_BN);
-
-	sys_fw_init(args, arglen);
+	bp = sys_fw_init(args, arglen);
 
 	ssc(0, (long) kpath, 0, 0, SSC_LOAD_SYMBOLS);
 
-	/*
-	 * Install the kernel's command line argument on ZERO_PAGE
-	 * just after the botoparam structure.
-	 * In case we don't have any argument just put \0
-	 */
-	memcpy(((struct ia64_boot_param *)ZERO_PAGE_ADDR) + 1, args, arglen);
-	sp = __pa(&stack);
-
-	asm volatile ("br.sptk.few %0" :: "b"(e_entry));
+	asm volatile ("mov sp=%2; mov r28=%1; br.sptk.few %0"
+		      :: "b"(e_entry), "r"(bp), "r"(__pa(&stack)));
 
 	cons_write("kernel returned!\n");
 	ssc(-1, 0, 0, 0, SSC_EXIT);
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/config.in linux/arch/ia64/config.in
--- v2.4.3/linux/arch/ia64/config.in	Fri Feb 16 15:53:08 2001
+++ linux/arch/ia64/config.in	Tue Apr 17 17:19:24 2001
@@ -23,6 +23,12 @@
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
 define_bool CONFIG_SBUS n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+
+choice 'IA-64 processor type' \
+	"Itanium			CONFIG_ITANIUM \
+	 McKinley			CONFIG_MCKINLEY" Itanium
 
 choice 'IA-64 system type'					\
 	"generic		CONFIG_IA64_GENERIC		\
@@ -36,24 +42,47 @@
 	 16KB			CONFIG_IA64_PAGE_SIZE_16KB		\
 	 64KB			CONFIG_IA64_PAGE_SIZE_64KB" 16KB
 
-if [ "$CONFIG_IA64_DIG" = "y" ]; then
-	define_bool CONFIG_ITANIUM y
+if [ "$CONFIG_ITANIUM" = "y" ]; then
 	define_bool CONFIG_IA64_BRL_EMU y
 	bool '  Enable Itanium A-step specific code' CONFIG_ITANIUM_ASTEP_SPECIFIC
 	bool '  Enable Itanium B-step specific code' CONFIG_ITANIUM_BSTEP_SPECIFIC
 	if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then
 	  bool '   Enable Itanium B0-step specific code' CONFIG_ITANIUM_B0_SPECIFIC
+        fi
+	if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then
 	  bool '   Enable Itanium B1-step specific code' CONFIG_ITANIUM_B1_SPECIFIC
+	fi
+	if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then
 	  bool '   Enable Itanium B2-step specific code' CONFIG_ITANIUM_B2_SPECIFIC
 	fi
 	bool '  Enable Itanium C-step specific code' CONFIG_ITANIUM_CSTEP_SPECIFIC
 	if [ "$CONFIG_ITANIUM_CSTEP_SPECIFIC" = "y" ]; then
 	  bool '   Enable Itanium C0-step specific code' CONFIG_ITANIUM_C0_SPECIFIC
 	fi
+	if [ "$CONFIG_ITANIUM_ASTEP_SPECIFIC" = "y" -o "$CONFIG_ITANIUM_B0_SPECIFIC" = "y" \
+	     -o "$CONFIG_ITANIUM_B1_SPECIFIC" = "y" -o "$CONFIG_ITANIUM_B2_SPECIFIC" = "y" ]; then
+	  define_bool CONFIG_ITANIUM_PTCG n
+	else
+	  define_bool CONFIG_ITANIUM_PTCG y
+	fi
+	if [ "$CONFIG_IA64_SGI_SN1" = "y" ]; then
+	  define_int CONFIG_IA64_L1_CACHE_SHIFT 7 # align cache-sensitive data to 128 bytes
+	else
+	  define_int CONFIG_IA64_L1_CACHE_SHIFT 6 # align cache-sensitive data to 64 bytes
+	fi
+fi
+
+if [ "$CONFIG_MCKINLEY" = "y" ]; then
+	define_bool CONFIG_ITANIUM_PTCG y
+	define_int CONFIG_IA64_L1_CACHE_SHIFT 7
+	bool '  Enable McKinley A-step specific code' CONFIG_MCKINLEY_ASTEP_SPECIFIC
+	if [ "$CONFIG_MCKINLEY_ASTEP_SPECIFIC" = "y" ]; then
+	  bool '   Enable McKinley A0/A1-step specific code' CONFIG_MCKINLEY_A0_SPECIFIC
+	fi
+fi
+
+if [ "$CONFIG_IA64_DIG" = "y" ]; then
 	bool '  Force interrupt redirection' CONFIG_IA64_HAVE_IRQREDIR
-	bool '  Enable use of global TLB purge instruction (ptc.g)' CONFIG_ITANIUM_PTCG
-	bool '  Enable SoftSDV hacks' CONFIG_IA64_SOFTSDV_HACKS
-	bool '  Enable AzusA hacks' CONFIG_IA64_AZUSA_HACKS
 	bool '  Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA
 	bool '  Enable ACPI 2.0 with errata 1.3' CONFIG_ACPI20
 	bool '  ACPI kernel configuration manager (EXPERIMENTAL)' CONFIG_ACPI_KERNEL_CONFIG
@@ -65,11 +94,6 @@
 fi
 
 if [ "$CONFIG_IA64_SGI_SN1" = "y" ]; then
-	bool '  Enable use of global TLB purge instruction (ptc.g)' CONFIG_ITANIUM_PTCG
-	bool '  Enable Itanium B-step specific code' CONFIG_ITANIUM_BSTEP_SPECIFIC
-	if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then
-	  bool '    Enable Itanium B0-step specific code' CONFIG_ITANIUM_B0_SPECIFIC
-	fi
 	bool '  Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN1_SIM
 	define_bool CONFIG_DEVFS_DEBUG y
 	define_bool CONFIG_DEVFS_FS y
@@ -87,7 +111,8 @@
 
 bool 'SMP support' CONFIG_SMP
 bool 'Performance monitor support' CONFIG_PERFMON
-bool '/proc/pal support' CONFIG_IA64_PALINFO
+tristate '/proc/pal support' CONFIG_IA64_PALINFO
+tristate '/proc/efi support' CONFIG_IA64_EFIVARS
 
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
@@ -253,7 +278,6 @@
 bool 'Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
 bool 'Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ
 bool 'Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS
-bool 'Enable new unwind support' CONFIG_IA64_NEW_UNWIND
 bool 'Disable VHPT' CONFIG_DISABLE_VHPT
 
 endmenu
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/dig/setup.c linux/arch/ia64/dig/setup.c
--- v2.4.3/linux/arch/ia64/dig/setup.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/dig/setup.c	Thu Apr  5 12:51:47 2001
@@ -1,9 +1,9 @@
 /*
- * Platform dependent support for Intel SoftSDV simulator.
+ * Platform dependent support for DIG64 platforms.
  *
  * Copyright (C) 1999 Intel Corp.
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999, 2001 Hewlett-Packard Co
+ * Copyright (C) 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
@@ -48,18 +48,14 @@
 	 */
 	ROOT_DEV = to_kdev_t(0x0802);		/* default to second partition on first drive */
 
-#ifdef	CONFIG_IA64_SOFTSDV_HACKS
-	ROOT_DEV = to_kdev_t(0x0302);		/* 2nd partion on 1st IDE */
-#endif /* CONFIG_IA64_SOFTSDV_HACKS */
-
 #ifdef CONFIG_SMP
 	init_smp_config();
 #endif
 
 	memset(&screen_info, 0, sizeof(screen_info));
 
-	if (!ia64_boot_param.console_info.num_rows
-	    || !ia64_boot_param.console_info.num_cols)
+	if (!ia64_boot_param->console_info.num_rows
+	    || !ia64_boot_param->console_info.num_cols)
 	{
 		printk("dig_setup: warning: invalid screen-info, guessing 80x25\n");
 		orig_x = 0;
@@ -68,10 +64,10 @@
 		num_rows = 25;
 		font_height = 16;
 	} else {
-		orig_x = ia64_boot_param.console_info.orig_x;
-		orig_y = ia64_boot_param.console_info.orig_y;
-		num_cols = ia64_boot_param.console_info.num_cols;
-		num_rows = ia64_boot_param.console_info.num_rows;
+		orig_x = ia64_boot_param->console_info.orig_x;
+		orig_y = ia64_boot_param->console_info.orig_y;
+		num_cols = ia64_boot_param->console_info.num_cols;
+		num_rows = ia64_boot_param->console_info.num_rows;
 		font_height = 400 / num_rows;
 	}
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/hp/hpsim_irq.c linux/arch/ia64/hp/hpsim_irq.c
--- v2.4.3/linux/arch/ia64/hp/hpsim_irq.c	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/hp/hpsim_irq.c	Thu Apr  5 12:51:47 2001
@@ -1,8 +1,8 @@
 /*
  * Platform dependent support for HP simulator.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #include <linux/init.h>
@@ -35,10 +35,12 @@
 void __init
 hpsim_irq_init (void)
 {
+	irq_desc_t *idesc;
 	int i;
 
-	for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) {
-		if (irq_desc[i].handler == &no_irq_type)
-			irq_desc[i].handler = &irq_type_hp_sim;
+	for (i = 0; i < NR_IRQS; ++i) {
+		idesc = irq_desc(i);
+		if (idesc->handler == &no_irq_type)
+			idesc->handler = &irq_type_hp_sim;
 	}
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/ia32/binfmt_elf32.c linux/arch/ia64/ia32/binfmt_elf32.c
--- v2.4.3/linux/arch/ia64/ia32/binfmt_elf32.c	Thu Mar 22 09:24:58 2001
+++ linux/arch/ia64/ia32/binfmt_elf32.c	Thu Apr  5 12:51:47 2001
@@ -57,28 +57,30 @@
 
 	if (page_count(page) != 1)
 		printk("mem_map disagrees with %p at %08lx\n", (void *) page, address);
+
 	pgd = pgd_offset(tsk->mm, address);
-	pmd = pmd_alloc(pgd, address);
-	if (!pmd) {
-		__free_page(page);
-		force_sig(SIGKILL, tsk);
-		return 0;
-	}
-	pte = pte_alloc(pmd, address);
-	if (!pte) {
-		__free_page(page);
-		force_sig(SIGKILL, tsk);
-		return 0;
-	}
-	if (!pte_none(*pte)) {
-		pte_ERROR(*pte);
-		__free_page(page);
-		return 0;
+
+	spin_lock(&tsk->mm->page_table_lock);
+	{
+		pmd = pmd_alloc(tsk->mm, pgd, address);
+		if (!pmd)
+			goto out;
+		pte = pte_alloc(tsk->mm, pmd, address);
+		if (!pte)
+			goto out;
+		if (!pte_none(*pte))
+			goto out;
+		flush_page_to_ram(page);
+		set_pte(pte, pte_mkwrite(mk_pte(page, PAGE_SHARED)));
 	}
-	flush_page_to_ram(page);
-	set_pte(pte, pte_mkwrite(mk_pte(page, PAGE_SHARED)));
+	spin_unlock(&tsk->mm->page_table_lock);
 	/* no need for flush_tlb */
 	return page;
+
+  out:
+	spin_unlock(&tsk->mm->page_table_lock);
+	__free_page(page);
+	return 0;
 }
 
 void ia64_elf32_init(struct pt_regs *regs)
@@ -90,12 +92,13 @@
 		put_shared_page(current, virt_to_page(ia32_tss), IA32_PAGE_OFFSET + PAGE_SIZE);
 
 	nr = smp_processor_id();
-	
+
 	/* Do all the IA-32 setup here */
 
-	current->thread.map_base  =  0x40000000;
-	current->thread.task_size =  0xc0000000;	/* use what Linux/x86 uses... */
- 
+	current->thread.map_base  = 0x40000000;
+	current->thread.task_size = 0xc0000000;		/* use what Linux/x86 uses... */
+	set_fs(USER_DS);				/* set addr limit for new TASK_SIZE */
+
 	/* setup ia32 state for ia32_load_state */
 
 	current->thread.eflag = IA32_EFLAG;
@@ -124,14 +127,8 @@
 		: "r" ((ulong)IA32_FCR_DEFAULT));
 	__asm__("mov ar.fir = r0");
 	__asm__("mov ar.fdr = r0");
-	__asm__("mov %0=ar.k0 ;;" : "=r" (current->thread.old_iob));
-	__asm__("mov ar.k0=%0 ;;" :: "r"(IA32_IOBASE));
-	/* TSS */
-	__asm__("mov ar.k1 = %0"
-		: /* no outputs */
-		: "r" IA64_SEG_DESCRIPTOR(IA32_PAGE_OFFSET + PAGE_SIZE,
-					  0x1FFFL, 0xBL, 1L,
-					  3L, 1L, 1L, 1L));
+	current->thread.old_iob = ia64_get_kr(IA64_KR_IO_BASE);
+	ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
 
 	/* Get the segment selectors right */
 	regs->r16 = (__USER_DS << 16) |  (__USER_DS); /* ES == DS, GS, FS are zero */
@@ -149,23 +146,10 @@
 	regs->r31 = IA64_SEG_DESCRIPTOR(0xc0000000L, 0x400L, 0x3L, 1L, 3L,
 					1L, 1L, 1L);
 
-       	/* Clear psr.ac */
+	/* Clear psr.ac */
 	regs->cr_ipsr &= ~IA64_PSR_AC;
 
 	regs->loadrs = 0;
-	/*
-	 *  According to the ABI %edx points to an `atexit' handler.
-	 *  Since we don't have one we'll set it to 0 and initialize
-	 *  all the other registers just to make things more deterministic,
-	 *  ala the i386 implementation.
-	 */
-	regs->r8 = 0;	/* %eax */
-	regs->r11 = 0;	/* %ebx */
-	regs->r9 = 0;	/* %ecx */
-	regs->r10 = 0;	/* %edx */
-	regs->r13 = 0;	/* %ebp */
-	regs->r14 = 0;	/* %esi */
-	regs->r15 = 0;	/* %edi */
 }
 
 #undef STACK_TOP
@@ -185,9 +169,9 @@
 	bprm->exec += stack_base;
 
 	mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
-	if (!mpnt) 
-		return -ENOMEM; 
-	
+	if (!mpnt)
+		return -ENOMEM;
+
 	{
 		mpnt->vm_mm = current->mm;
 		mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
@@ -200,7 +184,7 @@
 		mpnt->vm_private_data = 0;
 		insert_vm_struct(current->mm, mpnt);
 		current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
-	} 
+	}
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
 		if (bprm->page[i]) {
@@ -208,7 +192,7 @@
 		}
 		stack_base += PAGE_SIZE;
 	}
-	
+
 	return 0;
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/ia32/ia32_entry.S linux/arch/ia64/ia32/ia32_entry.S
--- v2.4.3/linux/arch/ia64/ia32/ia32_entry.S	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/ia32/ia32_entry.S	Thu Apr  5 12:51:47 2001
@@ -4,11 +4,34 @@
 
 #include "../kernel/entry.h"
 
+	/*
+	 * execve() is special because in case of success, we need to
+	 * setup a null register window frame (in case an IA-32 process
+	 * is exec'ing an IA-64 program).
+	 */
+ENTRY(ia32_execve)
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3)
+	alloc loc1=ar.pfs,3,2,4,0
+	mov loc0=rp
+	.body
+	mov out0=in0			// filename
+	;;				// stop bit between alloc and call
+	mov out1=in1			// argv
+	mov out2=in2			// envp
+	add out3=16,sp			// regs
+	br.call.sptk.few rp=sys32_execve
+1:	cmp4.ge p6,p0=r8,r0
+	mov ar.pfs=loc1			// restore ar.pfs
+	;;
+(p6)	mov ar.pfs=r0			// clear ar.pfs in case of success
+	sxt4 r8=r8			// return 64-bit result
+	mov rp=loc0
+	br.ret.sptk.few rp
+END(ia32_execve)
+
 	//
 	// Get possibly unaligned sigmask argument into an aligned
 	//   kernel buffer
-	.text
-
 GLOBAL_ENTRY(ia32_rt_sigsuspend)
 	// We'll cheat and not do an alloc here since we are ultimately
 	// going to do a simple branch to the IA64 sys_rt_sigsuspend.
@@ -16,38 +39,30 @@
 	// We copy this 4-byte aligned value to an 8-byte aligned buffer
 	// in the task structure and then jump to the IA64 code.
 
-	mov r8=r0		// no memory access errors yet
-	add r10=4,r32
-	;;
-1:
-	ld4 r2=[r32]		// get first half of sigmask
-	ld4 r3=[r10]		// get second half of sigmask
-2:
-	cmp.lt p6,p0=r8,r0	// check memory access
+	EX(.Lfail, ld4 r2=[r32],4)		// load low part of sigmask
 	;;
-(p6)	br.ret.sptk.many rp	//   it failed
-
+	EX(.Lfail, ld4 r3=[r32])		// load high part of sigmask
 	adds r32=IA64_TASK_THREAD_SIGMASK_OFFSET,r13
+	;;
+	st8 [r32]=r2
 	adds r10=IA64_TASK_THREAD_SIGMASK_OFFSET+4,r13
 	;;
-	st4 [r32]=r2
+
 	st4 [r10]=r3
 	br.cond.sptk.many sys_rt_sigsuspend
-END(ia32_rt_sigsuspend)
 
-	.section __ex_table,"a"
-	data4 @gprel(1b)
-	data4 (2b-1b)|1
-	.previous
+.Lfail:	br.ret.sptk.many rp	// failed to read sigmask
+END(ia32_rt_sigsuspend)
 
 GLOBAL_ENTRY(ia32_ret_from_syscall)
 	PT_REGS_UNWIND_INFO(0)
 
 	cmp.ge p6,p7=r8,r0                      // syscall executed successfully?
 	adds r2=IA64_PT_REGS_R8_OFFSET+16,sp    // r2 = &pt_regs.r8
-	;; 
+	;;
+	alloc r3=ar.pfs,0,0,0,0			// drop the syscall argument frame
 	st8 [r2]=r8                             // store return value in slot for r8
-	br.cond.sptk.few ia64_leave_kernel
+	br.cond.sptk.many ia64_leave_kernel
 END(ia32_ret_from_syscall)
 
 	//
@@ -69,7 +84,8 @@
 	;;
 	st8.spill [r2]=r8			// store return value in slot for r8
 	br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value
-.ret2:	br.cond.sptk.many ia64_leave_kernel	// rp MUST be != ia64_leave_kernel!
+.ret2:	alloc r2=ar.pfs,0,0,0,0			// drop the syscall argument frame
+	br.cond.sptk.many ia64_leave_kernel	// rp MUST be != ia64_leave_kernel!
 END(ia32_trace_syscall)
 
 GLOBAL_ENTRY(sys32_vfork)
@@ -79,7 +95,7 @@
 END(sys32_vfork)
 
 GLOBAL_ENTRY(sys32_fork)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
 	alloc r16=ar.pfs,2,2,4,0
 	mov out0=SIGCHLD			// out0 = clone_flags
 	;;
@@ -88,14 +104,14 @@
 	mov loc1=r16				// save ar.pfs across do_fork
 	DO_SAVE_SWITCH_STACK
 
-	UNW(.body)
+	.body
 
 	mov out1=0
 	mov out3=0
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
 	br.call.sptk.few rp=do_fork
 .ret3:	mov ar.pfs=loc1
-	UNW(.restore sp)
+	.restore sp
 	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop the switch stack
 	mov rp=loc0
 	br.ret.sptk.many rp
@@ -104,7 +120,7 @@
 	.rodata
 	.align 8
 	.globl ia32_syscall_table
-ia32_syscall_table:	
+ia32_syscall_table:
 	data8 sys32_ni_syscall	  /* 0	-  old "setup(" system call*/
 	data8 sys_exit
 	data8 sys32_fork
@@ -116,7 +132,7 @@
 	data8 sys_creat
 	data8 sys_link
 	data8 sys_unlink	  /* 10 */
-	data8 sys32_execve
+	data8 ia32_execve
 	data8 sys_chdir
 	data8 sys32_time
 	data8 sys_mknod
@@ -133,8 +149,8 @@
 	data8 sys32_ni_syscall /* sys_stime is not supported on IA64 */  /* 25 */
 	data8 sys32_ptrace
 	data8 sys32_alarm
-	data8 sys_pause
 	data8 sys32_ni_syscall
+	data8 sys_pause
 	data8 ia32_utime	  /* 30 */
 	data8 sys32_ni_syscall	  /* old stty syscall holder */
 	data8 sys32_ni_syscall	  /* old gtty syscall holder */
@@ -153,7 +169,7 @@
 	data8 sys_brk		  /* 45 */
 	data8 sys_setgid
 	data8 sys_getgid
-	data8 sys32_ni_syscall
+	data8 sys32_signal
 	data8 sys_geteuid
 	data8 sys_getegid	  /* 50 */
 	data8 sys_acct
@@ -227,7 +243,7 @@
 	data8 sys32_sigreturn
 	data8 sys_clone		  /* 120 */
 	data8 sys_setdomainname
-	data8 sys_newuname
+	data8 sys32_newuname
 	data8 sys_modify_ldt
 	data8 sys_adjtimex
 	data8 sys32_mprotect	  /* 125 */
@@ -249,12 +265,12 @@
 	data8 sys32_getdents
 	data8 sys32_select
 	data8 sys_flock
-	data8 sys_msync
+	data8 sys32_msync
 	data8 sys32_readv	  /* 145 */
 	data8 sys32_writev
 	data8 sys_getsid
 	data8 sys_fdatasync
-	data8 sys_sysctl
+	data8 sys32_sysctl
 	data8 sys_mlock		  /* 150 */
 	data8 sys_munlock
 	data8 sys_mlockall
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/ia32/ia32_support.c linux/arch/ia64/ia32/ia32_support.c
--- v2.4.3/linux/arch/ia64/ia32/ia32_support.c	Mon Oct  9 17:54:53 2000
+++ linux/arch/ia64/ia32/ia32_support.c	Thu Apr  5 12:51:47 2001
@@ -2,6 +2,7 @@
  * IA32 helper functions
  *
  * 06/16/00	A. Mallick	added csd/ssd/tssd for ia32 thread context
+ * 02/19/01	D. Mosberger	dropped tssd; it's not needed
  */
 
 #include <linux/kernel.h>
@@ -22,7 +23,7 @@
 void
 ia32_save_state (struct thread_struct *thread)
 {
-	unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd;
+	unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd;
 
 	asm ("mov %0=ar.eflag;"
 	     "mov %1=ar.fsr;"
@@ -31,9 +32,7 @@
 	     "mov %4=ar.fdr;"
 	     "mov %5=ar.csd;"
 	     "mov %6=ar.ssd;"
-	     "mov %7=ar.k1"
-	     : "=r"(eflag), "=r"(fsr), "=r"(fcr), "=r"(fir), "=r"(fdr),
-	       "=r"(csd), "=r"(ssd), "=r"(tssd));
+	     : "=r"(eflag), "=r"(fsr), "=r"(fcr), "=r"(fir), "=r"(fdr), "=r"(csd), "=r"(ssd));
 	thread->eflag = eflag;
 	thread->fsr = fsr;
 	thread->fcr = fcr;
@@ -41,14 +40,13 @@
 	thread->fdr = fdr;
 	thread->csd = csd;
 	thread->ssd = ssd;
-	thread->tssd = tssd;
 	asm ("mov ar.k0=%0 ;;" :: "r"(thread->old_iob));
 }
 
 void
 ia32_load_state (struct thread_struct *thread)
 {
-	unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd;
+	unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd;
 
 	eflag = thread->eflag;
 	fsr = thread->fsr;
@@ -57,7 +55,6 @@
 	fdr = thread->fdr;
 	csd = thread->csd;
 	ssd = thread->ssd;
-	tssd = thread->tssd;
 
 	asm volatile ("mov ar.eflag=%0;"
 		      "mov ar.fsr=%1;"
@@ -66,9 +63,7 @@
 		      "mov ar.fdr=%4;"
 		      "mov ar.csd=%5;"
 		      "mov ar.ssd=%6;"
-		      "mov ar.k1=%7"
-		      :: "r"(eflag), "r"(fsr), "r"(fcr), "r"(fir), "r"(fdr),
-		         "r"(csd), "r"(ssd), "r"(tssd));
+		      :: "r"(eflag), "r"(fsr), "r"(fcr), "r"(fir), "r"(fdr), "r"(csd), "r"(ssd));
 	asm ("mov %0=ar.k0 ;;" : "=r"(thread->old_iob));
 	asm ("mov ar.k0=%0 ;;" :: "r"(IA32_IOBASE));
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c
--- v2.4.3/linux/arch/ia64/ia32/sys_ia32.c	Mon Mar 19 12:35:10 2001
+++ linux/arch/ia64/ia32/sys_ia32.c	Thu Apr  5 12:51:47 2001
@@ -1,12 +1,12 @@
 /*
  * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on
- *             sys_sparc32 
+ *             sys_sparc32
  *
  * Copyright (C) 2000		VA Linux Co
  * Copyright (C) 2000		Don Dugger <n0ano@valinux.com>
- * Copyright (C) 1999 		Arun Sharma <arun.sharma@intel.com>
- * Copyright (C) 1997,1998 	Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1999		Arun Sharma <arun.sharma@intel.com>
+ * Copyright (C) 1997,1998	Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997		David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 2000		Hewlett-Packard Co.
  * Copyright (C) 2000		David Mosberger-Tang <davidm@hpl.hp.com>
  *
@@ -16,9 +16,10 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/sysctl.h>
 #include <linux/sched.h>
-#include <linux/fs.h> 
-#include <linux/file.h> 
+#include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/signal.h>
 #include <linux/utime.h>
 #include <linux/resource.h>
@@ -64,96 +65,87 @@
 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
 
 extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *);
-extern asmlinkage long sys_munmap (unsigned long, size_t len);
 extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long);
 
 static int
-nargs(unsigned int arg, char **ap)
+nargs (unsigned int arg, char **ap)
 {
 	int n, err, addr;
 
+	if (!arg)
+		return 0;
+
 	n = 0;
 	do {
 		err = get_user(addr, (int *)A(arg));
 		if (err)
 			return err;
-		if (ap) {		/* no access_ok needed, we allocated */
-			err = __put_user((char *)A(addr), ap++);
-			if (err)
-				return err;
-		}
+		if (ap)
+			*ap++ = (char *) A(addr);
 		arg += sizeof(unsigned int);
 		n++;
 	} while (addr);
-	return(n - 1);
+	return n - 1;
 }
 
 asmlinkage long
-sys32_execve(
-char *filename,
-unsigned int argv,
-unsigned int envp,
-int dummy3,
-int dummy4,
-int dummy5,
-int dummy6,
-int dummy7,
-int stack)
+sys32_execve (char *filename, unsigned int argv, unsigned int envp,
+	      int dummy3, int dummy4, int dummy5, int dummy6, int dummy7,
+	      int stack)
 {
 	struct pt_regs *regs = (struct pt_regs *)&stack;
+	unsigned long old_map_base, old_task_size;
 	char **av, **ae;
 	int na, ne, len;
 	long r;
 
 	na = nargs(argv, NULL);
 	if (na < 0)
-		return(na);
+		return na;
 	ne = nargs(envp, NULL);
 	if (ne < 0)
-		return(ne);
+		return ne;
 	len = (na + ne + 2) * sizeof(*av);
-	/*
-	 *  kmalloc won't work because the `sys_exec' code will attempt
-	 *  to do a `get_user' on the arg list and `get_user' will fail
-	 *  on a kernel address (simplifies `get_user').  Instead we
-	 *  do an mmap to get a user address.  Note that since a successful
-	 *  `execve' frees all current memory we only have to do an
-	 *  `munmap' if the `execve' failes.
-	 */
-	down_write(&current->mm->mmap_sem);
-
-	av = (char **) do_mmap_pgoff(0, 0UL, len, PROT_READ | PROT_WRITE,
-				     MAP_PRIVATE | MAP_ANONYMOUS, 0);
-
-	up_write(&current->mm->mmap_sem);
+	av = kmalloc(len, GFP_KERNEL);
+	if (!av)
+		return -ENOMEM;
 
-	if (IS_ERR(av))
-		return (long)av;
 	ae = av + na + 1;
-	r = __put_user(0, (av + na));
-	if (r)
-		goto out;
-	r = __put_user(0, (ae + ne));
-	if (r)
-		goto out;
+	av[na] = NULL;
+	ae[ne] = NULL;
+
 	r = nargs(argv, av);
 	if (r < 0)
 		goto out;
 	r = nargs(envp, ae);
 	if (r < 0)
 		goto out;
+
+	old_map_base  = current->thread.map_base;
+	old_task_size = current->thread.task_size;
+
+	/* we may be exec'ing a 64-bit process: reset map base & task-size: */
+	current->thread.map_base  = DEFAULT_MAP_BASE;
+	current->thread.task_size = DEFAULT_TASK_SIZE;
+
+	set_fs(KERNEL_DS);
 	r = sys_execve(filename, av, ae, regs);
-	if (r < 0)
-out:
-		sys_munmap((unsigned long) av, len);
-	return(r);
+	if (r < 0) {
+		/* oops, execve failed, switch back to old map base & task-size: */
+		current->thread.map_base  = old_map_base;
+		current->thread.task_size = old_task_size;
+		set_fs(USER_DS);	/* establish new task-size as the address-limit */
+	  out:
+		kfree(av);
+	}
+	return r;
 }
 
 static inline int
 putstat(struct stat32 *ubuf, struct stat *kbuf)
 {
 	int err;
-	
+
 	err = put_user (kbuf->st_dev, &ubuf->st_dev);
 	err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
 	err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
@@ -178,8 +170,8 @@
 	int ret;
 	struct stat s;
 	mm_segment_t old_fs = get_fs();
-	
-	set_fs (KERNEL_DS);
+
+	set_fs(KERNEL_DS);
 	ret = sys_newstat(filename, &s);
 	set_fs (old_fs);
 	if (putstat (statbuf, &s))
@@ -195,7 +187,7 @@
 	int ret;
 	struct stat s;
 	mm_segment_t old_fs = get_fs();
-	
+
 	set_fs (KERNEL_DS);
 	ret = sys_newlstat(filename, &s);
 	set_fs (old_fs);
@@ -212,7 +204,7 @@
 	int ret;
 	struct stat s;
 	mm_segment_t old_fs = get_fs();
-	
+
 	set_fs (KERNEL_DS);
 	ret = sys_newfstat(fd, &s);
 	set_fs (old_fs);
@@ -221,7 +213,6 @@
 	return ret;
 }
 
-#define ALIGN4K(a)	(((a) + 0xfff) & ~0xfff)
 #define OFFSET4K(a)	((a) & 0xfff)
 
 unsigned long
@@ -287,19 +278,19 @@
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	prot |= PROT_EXEC;
 
- 	if ((flags & MAP_FIXED) && ((addr & ~PAGE_MASK) || (offset & ~PAGE_MASK)))
- 		error = do_mmap_fake(file, addr, len, prot, flags, (loff_t)offset);
+	if ((flags & MAP_FIXED) && ((addr & ~PAGE_MASK) || (offset & ~PAGE_MASK)))
+		error = do_mmap_fake(file, addr, len, prot, flags, (loff_t)offset);
 	else {
- 		poff = offset & PAGE_MASK;
- 		len += offset - poff;
+		poff = offset & PAGE_MASK;
+		len += offset - poff;
+
+		down_write(&current->mm->mmap_sem);
+		error = do_mmap_pgoff(file, addr, len, prot, flags, poff >> PAGE_SHIFT);
+		up_write(&current->mm->mmap_sem);
 
- 		down_write(&current->mm->mmap_sem);
- 		error = do_mmap_pgoff(file, addr, len, prot, flags, poff >> PAGE_SHIFT);
-  		up_write(&current->mm->mmap_sem);
-
- 		if (!IS_ERR((void *) error))
- 			error += offset - poff;
- 	}
+		if (!IS_ERR((void *) error))
+			error += offset - poff;
+	}
 	return error;
 }
 
@@ -328,18 +319,46 @@
 	if (copy_from_user(&a, arg, sizeof(a)))
 		return -EFAULT;
 
+	if (PAGE_ALIGN(a.len) == 0)
+		return a.addr;
+
 	if (!(a.flags & MAP_ANONYMOUS)) {
 		file = fget(a.fd);
 		if (!file)
 			return -EBADF;
 	}
+#ifdef	CONFIG_IA64_PAGE_SIZE_4KB
+	if ((a.offset & ~PAGE_MASK) != 0)
+		return -EINVAL;
+
+	down_write(&current->mm->mmap_sem);
+	retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset >> PAGE_SHIFT);
+	up_write(&current->mm->mmap_sem);
+#else	// CONFIG_IA64_PAGE_SIZE_4KB
 	retval = ia32_do_mmap(file, a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+#endif	// CONFIG_IA64_PAGE_SIZE_4KB
 	if (file)
 		fput(file);
 	return retval;
 }
 
 asmlinkage long
+sys32_mprotect(unsigned long start, size_t len, unsigned long prot)
+{
+
+#ifdef	CONFIG_IA64_PAGE_SIZE_4KB
+	return(sys_mprotect(start, len, prot));
+#else	// CONFIG_IA64_PAGE_SIZE_4KB
+	if (prot == 0)
+		return(0);
+	len += start & ~PAGE_MASK;
+	if ((start & ~PAGE_MASK) && (prot & PROT_WRITE))
+		prot |= PROT_EXEC;
+	return(sys_mprotect(start & PAGE_MASK, len & PAGE_MASK, prot));
+#endif	// CONFIG_IA64_PAGE_SIZE_4KB
+}
+
+asmlinkage long
 sys32_pipe(int *fd)
 {
 	int retval;
@@ -355,15 +374,17 @@
 }
 
 asmlinkage long
-sys32_mprotect(unsigned long start, size_t len, unsigned long prot)
+sys32_signal (int sig, unsigned int handler)
 {
+	struct k_sigaction new_sa, old_sa;
+	int ret;
 
-	if (prot == 0)
-		return(0);
-	len += start & ~PAGE_MASK;
-	if ((start & ~PAGE_MASK) && (prot & PROT_WRITE))
-		prot |= PROT_EXEC;
-	return(sys_mprotect(start & PAGE_MASK, len & PAGE_MASK, prot));
+	new_sa.sa.sa_handler = (__sighandler_t) A(handler);
+	new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;
+
+	ret = do_sigaction(sig, &new_sa, &old_sa);
+
+	return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
 }
 
 asmlinkage long
@@ -393,7 +414,7 @@
 				| (((long)set32.sig[1]) << 32);
 		}
 		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		
+
 		if (ret)
 			return -EFAULT;
 	}
@@ -436,7 +457,7 @@
 	sigset32_t s32;
 	int ret;
 	mm_segment_t old_fs = get_fs();
-	
+
 	if (set) {
 		if (copy_from_user (&s32, set, sizeof(sigset32_t)))
 			return -EFAULT;
@@ -449,7 +470,7 @@
 	}
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL,
-				 sigsetsize); 
+				 sigsetsize);
 	set_fs (old_fs);
 	if (ret) return ret;
 	if (oset) {
@@ -469,7 +490,7 @@
 put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
 {
 	int err;
-	
+
 	err = put_user (kbuf->f_type, &ubuf->f_type);
 	err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
 	err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
@@ -491,7 +512,7 @@
 	int ret;
 	struct statfs s;
 	mm_segment_t old_fs = get_fs();
-	
+
 	set_fs (KERNEL_DS);
 	ret = sys_statfs((const char *)path, &s);
 	set_fs (old_fs);
@@ -508,7 +529,7 @@
 	int ret;
 	struct statfs s;
 	mm_segment_t old_fs = get_fs();
-	
+
 	set_fs (KERNEL_DS);
 	ret = sys_fstatfs(fd, &s);
 	set_fs (old_fs);
@@ -534,7 +555,6 @@
 	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
 		(__get_user(o->tv_sec, &i->tv_sec) |
 		 __get_user(o->tv_usec, &i->tv_usec)));
-	return ENOSYS;
 }
 
 static inline long
@@ -553,18 +573,16 @@
 		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
 		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
 		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
-	return ENOSYS;
 }
 
 static inline long
 put_it32(struct itimerval32 *o, struct itimerval *i)
 {
-	return (!access_ok(VERIFY_WRITE, i, sizeof(*i)) ||
+	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
 		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
 		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
 		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
-	return ENOSYS;
 }
 
 extern int do_getitimer(int which, struct itimerval *value);
@@ -605,7 +623,7 @@
 	return 0;
 
 }
-asmlinkage unsigned long 
+asmlinkage unsigned long
 sys32_alarm(unsigned int seconds)
 {
 	struct itimerval it_new, it_old;
@@ -638,7 +656,7 @@
 ia32_utime(char * filename, struct utimbuf_32 *times32)
 {
 	mm_segment_t old_fs = get_fs();
-	struct timeval tv[2];
+	struct timeval tv[2], *tvp;
 	long ret;
 
 	if (times32) {
@@ -647,15 +665,10 @@
 		get_user(tv[1].tv_sec, &times32->mtime);
 		tv[1].tv_usec = 0;
 		set_fs (KERNEL_DS);
-	} else {
-		set_fs (KERNEL_DS);
-		ret = sys_gettimeofday(&tv[0], 0);
-		if (ret < 0)
-			goto out;
-		tv[1] = tv[0];
-	}
-	ret = sys_utimes(filename, tv);
-  out:
+		tvp = tv;
+	} else
+		tvp = NULL;
+	ret = sys_utimes(filename, tvp);
 	set_fs (old_fs);
 	return ret;
 }
@@ -685,7 +698,7 @@
 	struct timeval ktv;
 	struct timezone ktz;
 
- 	if (tv) {
+	if (tv) {
 		if (get_tv32(&ktv, tv))
 			return -EFAULT;
 	}
@@ -872,7 +885,7 @@
 	/*
 	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
 	 * since we used fdset we need to allocate memory in units of
-	 * long-words. 
+	 * long-words.
 	 */
 	ret = -ENOMEM;
 	size = FDS_BYTES(n);
@@ -946,11 +959,11 @@
 }
 
 struct timespec32 {
-	int 	tv_sec;
+	int	tv_sec;
 	int	tv_nsec;
 };
 
-extern asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp); 
+extern asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
 
 asmlinkage long
 sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
@@ -958,7 +971,7 @@
 	struct timespec t;
 	int ret;
 	mm_segment_t old_fs = get_fs ();
-	
+
 	if (get_user (t.tv_sec, &rqtp->tv_sec) ||
 	    __get_user (t.tv_nsec, &rqtp->tv_nsec))
 		return -EFAULT;
@@ -967,7 +980,7 @@
 	set_fs (old_fs);
 	if (rmtp && ret == -EINTR) {
 		if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
-	    	    __put_user (t.tv_nsec, &rmtp->tv_nsec))
+		    __put_user (t.tv_nsec, &rmtp->tv_nsec))
 			return -EFAULT;
 	}
 	return ret;
@@ -1072,7 +1085,7 @@
 	struct rlimit r;
 	int ret;
 	mm_segment_t old_fs = get_fs ();
-	
+
 	set_fs (KERNEL_DS);
 	ret = sys_getrlimit(resource, &r);
 	set_fs (old_fs);
@@ -1092,7 +1105,7 @@
 	int ret;
 	mm_segment_t old_fs = get_fs ();
 
-	if (resource >= RLIM_NLIMITS) return -EINVAL;	
+	if (resource >= RLIM_NLIMITS) return -EINVAL;
 	if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
 	    __get_user (r.rlim_max, &rlim->rlim_max))
 		return -EFAULT;
@@ -1109,7 +1122,7 @@
 /*
  *  Declare the IA32 version of the msghdr
  */
- 
+
 struct msghdr32 {
 	unsigned int    msg_name;	/* Socket name			*/
 	int		msg_namelen;	/* Length of name		*/
@@ -1157,7 +1170,7 @@
 {
 	int size, err, ct;
 	struct iovec32 *iov32;
-	
+
 	if(m->msg_namelen)
 	{
 		if(mode==VERIFY_READ)
@@ -1166,7 +1179,7 @@
 			if(err<0)
 				goto out;
 		}
-		
+
 		m->msg_name = address;
 	} else
 		m->msg_name = NULL;
@@ -1195,7 +1208,7 @@
 }
 
 /* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
+#define MAX_SOCK_ADDR	128		/* 108 for Unix domain -
 					   16 for IP, 16 for IPX,
 					   24 for IPv6,
 					   about 80 for AX.25 */
@@ -1215,13 +1228,13 @@
 	unsigned char *ctl_buf = ctl;
 	struct msghdr msg_sys;
 	int err, ctl_len, iov_size, total_len;
-	
+
 	err = -EFAULT;
 	if (shape_msg(&msg_sys, msg))
-		goto out; 
+		goto out;
 
 	sock = sockfd_lookup(fd, &err);
-	if (!sock) 
+	if (!sock)
 		goto out;
 
 	/* do not move before msg_sys is valid */
@@ -1240,7 +1253,7 @@
 
 	/* This will also move the address data into kernel space */
 	err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
-	if (err < 0) 
+	if (err < 0)
 		goto out_freeiov;
 	total_len = err;
 
@@ -1248,14 +1261,14 @@
 
 	if (msg_sys.msg_controllen > INT_MAX)
 		goto out_freeiov;
-	ctl_len = msg_sys.msg_controllen; 
-	if (ctl_len) 
+	ctl_len = msg_sys.msg_controllen;
+	if (ctl_len)
 	{
 		if (ctl_len > sizeof(ctl))
 		{
 			err = -ENOBUFS;
 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
-			if (ctl_buf == NULL) 
+			if (ctl_buf == NULL)
 				goto out_freeiov;
 		}
 		err = -EFAULT;
@@ -1270,14 +1283,14 @@
 	err = sock_sendmsg(sock, &msg_sys, total_len);
 
 out_freectl:
-	if (ctl_buf != ctl)    
+	if (ctl_buf != ctl)
 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
 out_freeiov:
 	if (iov != iovstack)
 		sock_kfree_s(sock->sk, iov, iov_size);
 out_put:
 	sockfd_put(sock);
-out:       
+out:
 	return err;
 }
 
@@ -1301,7 +1314,7 @@
 	/* user mode address pointers */
 	struct sockaddr *uaddr;
 	int *uaddr_len;
-	
+
 	err=-EFAULT;
 	if (shape_msg(&msg_sys, msg))
 		goto out;
@@ -1313,7 +1326,7 @@
 	err = -EINVAL;
 	if (msg_sys.msg_iovlen > UIO_MAXIOV)
 		goto out_put;
-	
+
 	/* Check whether to allocate the iovec area*/
 	err = -ENOMEM;
 	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
@@ -1327,7 +1340,7 @@
 	 *	Save the user-mode address (verify_iovec will change the
 	 *	kernel msghdr to use the kernel address space)
 	 */
-	 
+
 	uaddr = msg_sys.msg_name;
 	uaddr_len = &msg->msg_namelen;
 	err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
@@ -1337,7 +1350,7 @@
 
 	cmsg_ptr = (unsigned long)msg_sys.msg_control;
 	msg_sys.msg_flags = 0;
-	
+
 	if (sock->file->f_flags & O_NONBLOCK)
 		flags |= MSG_DONTWAIT;
 	err = sock_recvmsg(sock, &msg_sys, total_len, flags);
@@ -1353,7 +1366,7 @@
 	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
 	if (err)
 		goto out_freeiov;
-	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
+	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr,
 							 &msg->msg_controllen);
 	if (err)
 		goto out_freeiov;
@@ -1371,15 +1384,15 @@
 /* Argument list sizes for sys_socketcall */
 #define AL(x) ((x) * sizeof(u32))
 static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
-                                AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-                                AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+				AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+				AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
 #undef AL
 
 extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
 extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
 				  int addrlen);
 extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
-				 int *upeer_addrlen); 
+				 int *upeer_addrlen);
 extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
 				      int *usockaddr_len);
 extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
@@ -1406,15 +1419,15 @@
 	int ret;
 	u32 a[6];
 	u32 a0,a1;
-				 
+
 	if (call<SYS_SOCKET||call>SYS_RECVMSG)
 		return -EINVAL;
 	if (copy_from_user(a, args, nas[call]))
 		return -EFAULT;
 	a0=a[0];
 	a1=a[1];
-	
-	switch(call) 
+
+	switch(call)
 	{
 		case SYS_SOCKET:
 			ret = sys_socket(a0, a1, a[2]);
@@ -1490,52 +1503,52 @@
 
 struct ipc_perm32
 {
-	key_t    	  key;
-        __kernel_uid_t32  uid;
-        __kernel_gid_t32  gid;
-        __kernel_uid_t32  cuid;
-        __kernel_gid_t32  cgid;
-        __kernel_mode_t32 mode;
-        unsigned short  seq;
+	key_t	  key;
+	__kernel_uid_t32  uid;
+	__kernel_gid_t32  gid;
+	__kernel_uid_t32  cuid;
+	__kernel_gid_t32  cgid;
+	__kernel_mode_t32 mode;
+	unsigned short  seq;
 };
 
 struct semid_ds32 {
-        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
-        __kernel_time_t32 sem_otime;              /* last semop time */
-        __kernel_time_t32 sem_ctime;              /* last change time */
-        u32 sem_base;              /* ptr to first semaphore in array */
-        u32 sem_pending;          /* pending operations to be processed */
-        u32 sem_pending_last;    /* last pending operation */
-        u32 undo;                  /* undo requests on this array */
-        unsigned short  sem_nsems;              /* no. of semaphores in array */
+	struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
+	__kernel_time_t32 sem_otime;              /* last semop time */
+	__kernel_time_t32 sem_ctime;              /* last change time */
+	u32 sem_base;              /* ptr to first semaphore in array */
+	u32 sem_pending;          /* pending operations to be processed */
+	u32 sem_pending_last;    /* last pending operation */
+	u32 undo;                  /* undo requests on this array */
+	unsigned short  sem_nsems;              /* no. of semaphores in array */
 };
 
 struct msqid_ds32
 {
-        struct ipc_perm32 msg_perm;
-        u32 msg_first;
-        u32 msg_last;
-        __kernel_time_t32 msg_stime;
-        __kernel_time_t32 msg_rtime;
-        __kernel_time_t32 msg_ctime;
-        u32 wwait;
-        u32 rwait;
-        unsigned short msg_cbytes;
-        unsigned short msg_qnum;  
-        unsigned short msg_qbytes;
-        __kernel_ipc_pid_t32 msg_lspid;
-        __kernel_ipc_pid_t32 msg_lrpid;
+	struct ipc_perm32 msg_perm;
+	u32 msg_first;
+	u32 msg_last;
+	__kernel_time_t32 msg_stime;
+	__kernel_time_t32 msg_rtime;
+	__kernel_time_t32 msg_ctime;
+	u32 wwait;
+	u32 rwait;
+	unsigned short msg_cbytes;
+	unsigned short msg_qnum;
+	unsigned short msg_qbytes;
+	__kernel_ipc_pid_t32 msg_lspid;
+	__kernel_ipc_pid_t32 msg_lrpid;
 };
 
 struct shmid_ds32 {
-        struct ipc_perm32       shm_perm;
-        int                     shm_segsz;
-        __kernel_time_t32       shm_atime;
-        __kernel_time_t32       shm_dtime;
-        __kernel_time_t32       shm_ctime;
-        __kernel_ipc_pid_t32    shm_cpid; 
-        __kernel_ipc_pid_t32    shm_lpid; 
-        unsigned short          shm_nattch;
+	struct ipc_perm32       shm_perm;
+	int                     shm_segsz;
+	__kernel_time_t32       shm_atime;
+	__kernel_time_t32       shm_dtime;
+	__kernel_time_t32       shm_ctime;
+	__kernel_ipc_pid_t32    shm_cpid;
+	__kernel_ipc_pid_t32    shm_lpid;
+	unsigned short          shm_nattch;
 };
 
 #define IPCOP_MASK(__x)	(1UL << (__x))
@@ -1876,7 +1889,7 @@
 		err = do_sys32_shmat (first, second, third,
 				      version, (void *)AA(ptr));
 		break;
-	case SHMDT: 
+	case SHMDT:
 		err = sys_shmdt ((char *)AA(ptr));
 		break;
 	case SHMGET:
@@ -1902,7 +1915,7 @@
 {
 	int i;
 
-	/* SMP: This is fairly trivial. We grab CURRENT_TIME and 
+	/* SMP: This is fairly trivial. We grab CURRENT_TIME and
 	   stuff it to user space. No side effects */
 	i = CURRENT_TIME;
 	if (tloc) {
@@ -1913,29 +1926,29 @@
 }
 
 struct rusage32 {
-        struct timeval32 ru_utime;
-        struct timeval32 ru_stime;
-        int    ru_maxrss;
-        int    ru_ixrss;
-        int    ru_idrss;
-        int    ru_isrss;
-        int    ru_minflt;
-        int    ru_majflt;
-        int    ru_nswap;
-        int    ru_inblock;
-        int    ru_oublock;
-        int    ru_msgsnd; 
-        int    ru_msgrcv; 
-        int    ru_nsignals;
-        int    ru_nvcsw;
-        int    ru_nivcsw;
+	struct timeval32 ru_utime;
+	struct timeval32 ru_stime;
+	int    ru_maxrss;
+	int    ru_ixrss;
+	int    ru_idrss;
+	int    ru_isrss;
+	int    ru_minflt;
+	int    ru_majflt;
+	int    ru_nswap;
+	int    ru_inblock;
+	int    ru_oublock;
+	int    ru_msgsnd;
+	int    ru_msgrcv;
+	int    ru_nsignals;
+	int    ru_nvcsw;
+	int    ru_nivcsw;
 };
 
 static int
 put_rusage (struct rusage32 *ru, struct rusage *r)
 {
 	int err;
-	
+
 	err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
 	err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
 	err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
@@ -1968,7 +1981,7 @@
 		int ret;
 		unsigned int status;
 		mm_segment_t old_fs = get_fs();
-		
+
 		set_fs (KERNEL_DS);
 		ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
 		set_fs (old_fs);
@@ -1995,7 +2008,7 @@
 	struct rusage r;
 	int ret;
 	mm_segment_t old_fs = get_fs();
-		
+
 	set_fs (KERNEL_DS);
 	ret = sys_getrusage(who, &r);
 	set_fs (old_fs);
@@ -2009,7 +2022,7 @@
 	__kernel_clock_t32 tms_cutime;
 	__kernel_clock_t32 tms_cstime;
 };
-                                
+
 extern asmlinkage long sys_times(struct tms * tbuf);
 
 asmlinkage long
@@ -2019,7 +2032,7 @@
 	long ret;
 	mm_segment_t old_fs = get_fs ();
 	int err;
-	
+
 	set_fs (KERNEL_DS);
 	ret = sys_times(tbuf ? &t : NULL);
 	set_fs (old_fs);
@@ -2069,7 +2082,7 @@
 #define PT_GS	10
 #define PT_ORIG_EAX 11
 #define PT_EIP	12
-#define PT_CS 	13
+#define PT_CS	13
 #define PT_EFL	14
 #define PT_UESP	15
 #define PT_SS	16
@@ -2385,7 +2398,7 @@
 		break;
 
 	      case IA32_PTRACE_GETREGS:
-	  	if (!access_ok(VERIFY_WRITE, (int *)data, 17*sizeof(int))) {
+		if (!access_ok(VERIFY_WRITE, (int *)data, 17*sizeof(int))) {
 			ret = -EIO;
 			break;
 		}
@@ -2399,7 +2412,7 @@
 	      case IA32_PTRACE_SETREGS:
 	      {
 		unsigned int tmp;
-	  	if (!access_ok(VERIFY_READ, (int *)data, 17*sizeof(int))) {
+		if (!access_ok(VERIFY_READ, (int *)data, 17*sizeof(int))) {
 			ret = -EIO;
 			break;
 		}
@@ -2444,7 +2457,7 @@
 get_flock32(struct flock *kfl, struct flock32 *ufl)
 {
 	int err;
-	
+
 	err = get_user(kfl->l_type, &ufl->l_type);
 	err |= __get_user(kfl->l_whence, &ufl->l_whence);
 	err |= __get_user(kfl->l_start, &ufl->l_start);
@@ -2457,7 +2470,7 @@
 put_flock32(struct flock *kfl, struct flock32 *ufl)
 {
 	int err;
-	
+
 	err = __put_user(kfl->l_type, &ufl->l_type);
 	err |= __put_user(kfl->l_whence, &ufl->l_whence);
 	err |= __put_user(kfl->l_start, &ufl->l_start);
@@ -2480,7 +2493,7 @@
 	case F_GETLK:
 	case F_SETLK:
 	case F_SETLKW:
-		if(cmd != F_GETLK && get_flock32(&f, (struct flock32 *)((long)arg)))
+		if(get_flock32(&f, (struct flock32 *)((long)arg)))
 			return -EFAULT;
 		old_fs = get_fs();
 		set_fs(KERNEL_DS);
@@ -2501,27 +2514,27 @@
 asmlinkage long
 sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
 {
-        struct k_sigaction new_ka, old_ka;
-        int ret;
+	struct k_sigaction new_ka, old_ka;
+	int ret;
 
-        if (act) {
+	if (act) {
 		old_sigset32_t mask;
-		
+
 		ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
 		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		ret |= __get_user(mask, &act->sa_mask);
 		if (ret)
 			return ret;
 		siginitset(&new_ka.sa.sa_mask, mask);
-        }
+	}
 
-        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
 		ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
 		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 		ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-        }
+	}
 
 	return ret;
 }
@@ -2658,6 +2671,85 @@
 	return -ERESTARTNOHAND;
 }
 
+asmlinkage long sys_msync(unsigned long start, size_t len, int flags);
+
+asmlinkage int
+sys32_msync(unsigned int start, unsigned int len, int flags)
+{
+	unsigned int addr;
+
+	if (OFFSET4K(start))
+		return -EINVAL;
+	addr = start & PAGE_MASK;
+	return(sys_msync(addr, len + (start - addr), flags));
+}
+
+struct sysctl_ia32 {
+	unsigned int	name;
+	int		nlen;
+	unsigned int	oldval;
+	unsigned int	oldlenp;
+	unsigned int	newval;
+	unsigned int	newlen;
+	unsigned int	__unused[4];
+};
+
+extern asmlinkage long sys_sysctl(struct __sysctl_args *args);
+
+asmlinkage long
+sys32_sysctl(struct sysctl_ia32 *args32)
+{
+	struct sysctl_ia32 a32;
+	mm_segment_t old_fs = get_fs ();
+	void *oldvalp, *newvalp;
+	size_t oldlen;
+	int *namep;
+	long ret;
+
+	if (copy_from_user(&a32, args32, sizeof (a32)))
+		return -EFAULT;
+
+	/*
+	 * We need to pre-validate these because we have to disable address checking
+	 * before calling do_sysctl() because of OLDLEN but we can't run the risk of the
+	 * user specifying bad addresses here.  Well, since we're dealing with 32 bit
+	 * addresses, we KNOW that access_ok() will always succeed, so this is an
+	 * expensive NOP, but so what...
+	 */
+	namep = (int *) A(a32.name);
+	oldvalp = (void *) A(a32.oldval);
+	newvalp = (void *) A(a32.newval);
+
+	if ((oldvalp && get_user(oldlen, (int *) A(a32.oldlenp)))
+	    || !access_ok(VERIFY_WRITE, namep, 0)
+	    || !access_ok(VERIFY_WRITE, oldvalp, 0)
+	    || !access_ok(VERIFY_WRITE, newvalp, 0))
+		return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	lock_kernel();
+	ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen);
+	unlock_kernel();
+	set_fs(old_fs);
+
+	if (oldvalp && put_user (oldlen, (int *) A(a32.oldlenp)))
+		return -EFAULT;
+
+	return ret;
+}
+
+asmlinkage long
+sys32_newuname(struct new_utsname * name)
+{
+	extern asmlinkage long sys_newuname(struct new_utsname * name);
+	int ret = sys_newuname(name);
+
+	if (!ret)
+		if (copy_to_user(name->machine, "i686\0\0\0", 8))
+			ret = -EFAULT;
+	return ret;
+}
+
 #ifdef	NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
 
 /* In order to reduce some races, while at the same time doing additional
@@ -2721,7 +2813,7 @@
     __kernel_time_t32 dqb_btime;
     __kernel_time_t32 dqb_itime;
 };
-                                
+
 extern asmlinkage long sys_quotactl(int cmd, const char *special, int id,
 				   caddr_t addr);
 
@@ -2733,7 +2825,7 @@
 	struct dqblk d;
 	mm_segment_t old_fs;
 	char *spec;
-	
+
 	switch (cmds) {
 	case Q_GETQUOTA:
 		break;
@@ -2782,7 +2874,7 @@
 	mm_segment_t old_fs;
 	int ret;
 	char *filenam;
-	
+
 	if (!times)
 		return sys_utime(filename, NULL);
 	if (get_user (t.actime, &times->actime) ||
@@ -2792,7 +2884,7 @@
 	ret = PTR_ERR(filenam);
 	if (!IS_ERR(filenam)) {
 		old_fs = get_fs();
-		set_fs (KERNEL_DS); 
+		set_fs (KERNEL_DS);
 		ret = sys_utime(filenam, &t);
 		set_fs (old_fs);
 		putname (filenam);
@@ -2869,18 +2961,18 @@
 }
 
 struct ncp_mount_data32 {
-        int version;
-        unsigned int ncp_fd;
-        __kernel_uid_t32 mounted_uid;
-        __kernel_pid_t32 wdog_pid;
-        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
-        unsigned int time_out;
-        unsigned int retry_count;
-        unsigned int flags;
-        __kernel_uid_t32 uid;
-        __kernel_gid_t32 gid;
-        __kernel_mode_t32 file_mode;
-        __kernel_mode_t32 dir_mode;
+	int version;
+	unsigned int ncp_fd;
+	__kernel_uid_t32 mounted_uid;
+	__kernel_pid_t32 wdog_pid;
+	unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
+	unsigned int time_out;
+	unsigned int retry_count;
+	unsigned int flags;
+	__kernel_uid_t32 uid;
+	__kernel_gid_t32 gid;
+	__kernel_mode_t32 file_mode;
+	__kernel_mode_t32 dir_mode;
 };
 
 static void *
@@ -2901,12 +2993,12 @@
 }
 
 struct smb_mount_data32 {
-        int version;
-        __kernel_uid_t32 mounted_uid;
-        __kernel_uid_t32 uid;
-        __kernel_gid_t32 gid;
-        __kernel_mode_t32 file_mode;
-        __kernel_mode_t32 dir_mode;
+	int version;
+	__kernel_uid_t32 mounted_uid;
+	__kernel_uid_t32 uid;
+	__kernel_gid_t32 gid;
+	__kernel_mode_t32 file_mode;
+	__kernel_mode_t32 dir_mode;
 };
 
 static void *
@@ -3020,16 +3112,16 @@
 }
 
 struct sysinfo32 {
-        s32 uptime;
-        u32 loads[3];
-        u32 totalram;
-        u32 freeram;
-        u32 sharedram;
-        u32 bufferram;
-        u32 totalswap;
-        u32 freeswap;
-        unsigned short procs;
-        char _f[22];
+	s32 uptime;
+	u32 loads[3];
+	u32 totalram;
+	u32 freeram;
+	u32 sharedram;
+	u32 bufferram;
+	u32 totalswap;
+	u32 freeswap;
+	unsigned short procs;
+	char _f[22];
 };
 
 extern asmlinkage long sys_sysinfo(struct sysinfo *info);
@@ -3040,7 +3132,7 @@
 	struct sysinfo s;
 	int ret, err;
 	mm_segment_t old_fs = get_fs ();
-	
+
 	set_fs (KERNEL_DS);
 	ret = sys_sysinfo(&s);
 	set_fs (old_fs);
@@ -3059,7 +3151,7 @@
 		return -EFAULT;
 	return ret;
 }
-                
+
 extern asmlinkage long sys_sched_rr_get_interval(pid_t pid,
 						struct timespec *interval);
 
@@ -3069,7 +3161,7 @@
 	struct timespec t;
 	int ret;
 	mm_segment_t old_fs = get_fs ();
-	
+
 	set_fs (KERNEL_DS);
 	ret = sys_sched_rr_get_interval(pid, &t);
 	set_fs (old_fs);
@@ -3088,7 +3180,7 @@
 	old_sigset_t s;
 	int ret;
 	mm_segment_t old_fs = get_fs();
-	
+
 	if (set && get_user (s, set)) return -EFAULT;
 	set_fs (KERNEL_DS);
 	ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
@@ -3106,7 +3198,7 @@
 	old_sigset_t s;
 	int ret;
 	mm_segment_t old_fs = get_fs();
-		
+
 	set_fs (KERNEL_DS);
 	ret = sys_sigpending(&s);
 	set_fs (old_fs);
@@ -3123,7 +3215,7 @@
 	sigset_t32 s32;
 	int ret;
 	mm_segment_t old_fs = get_fs();
-		
+
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigpending(&s, sigsetsize);
 	set_fs (old_fs);
@@ -3234,7 +3326,7 @@
 	mm_segment_t old_fs = get_fs();
 	siginfo_t info;
 	siginfo_t32 info32;
-		
+
 	if (copy_from_user (&s32, uthese, sizeof(sigset_t32)))
 		return -EFAULT;
 	switch (_NSIG_WORDS) {
@@ -3270,7 +3362,7 @@
 	siginfo_t32 info32;
 	int ret;
 	mm_segment_t old_fs = get_fs();
-	
+
 	if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32)))
 		return -EFAULT;
 	/* XXX: Is this correct? */
@@ -3315,7 +3407,7 @@
 	uid_t a, b, c;
 	int ret;
 	mm_segment_t old_fs = get_fs();
-		
+
 	set_fs (KERNEL_DS);
 	ret = sys_getresuid(&a, &b, &c);
 	set_fs (old_fs);
@@ -3354,12 +3446,12 @@
 
 asmlinkage long
 sys32_getresgid(__kernel_gid_t32 *rgid, __kernel_gid_t32 *egid,
-		__kernel_gid_t32 *sgid) 
+		__kernel_gid_t32 *sgid)
 {
 	gid_t a, b, c;
 	int ret;
 	mm_segment_t old_fs = get_fs();
-		
+
 	set_fs (KERNEL_DS);
 	ret = sys_getresgid(&a, &b, &c);
 	set_fs (old_fs);
@@ -3379,7 +3471,7 @@
 	gid_t gl[NGROUPS];
 	int ret, i;
 	mm_segment_t old_fs = get_fs ();
-	
+
 	set_fs (KERNEL_DS);
 	ret = sys_getgroups(gidsetsize, gl);
 	set_fs (old_fs);
@@ -3398,13 +3490,13 @@
 	gid_t gl[NGROUPS];
 	int ret, i;
 	mm_segment_t old_fs = get_fs ();
-	
+
 	if ((unsigned) gidsetsize > NGROUPS)
 		return -EINVAL;
 	for (i = 0; i < gidsetsize; i++, grouplist++)
 		if (__get_user (gl[i], grouplist))
 			return -EFAULT;
-        set_fs (KERNEL_DS);
+	set_fs (KERNEL_DS);
 	ret = sys_setgroups(gidsetsize, gl);
 	set_fs (old_fs);
 	return ret;
@@ -3442,26 +3534,26 @@
 }
 
 struct msghdr32 {
-        u32               msg_name;
-        int               msg_namelen;
-        u32               msg_iov;
-        __kernel_size_t32 msg_iovlen;
-        u32               msg_control;
-        __kernel_size_t32 msg_controllen;
-        unsigned          msg_flags;
+	u32               msg_name;
+	int               msg_namelen;
+	u32               msg_iov;
+	__kernel_size_t32 msg_iovlen;
+	u32               msg_control;
+	__kernel_size_t32 msg_controllen;
+	unsigned          msg_flags;
 };
 
 struct cmsghdr32 {
-        __kernel_size_t32 cmsg_len;
-        int               cmsg_level;
-        int               cmsg_type;
+	__kernel_size_t32 cmsg_len;
+	int               cmsg_level;
+	int               cmsg_type;
 };
 
 /* Bleech... */
 #define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) \
-        __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
+	__cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
 #define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) \
-        cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
+	cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
 
 #define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
 
@@ -3479,7 +3571,7 @@
 
 __inline__ struct cmsghdr32 *
 __cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-		struct cmsghdr32 *__cmsg, int __cmsg_len) 
+		struct cmsghdr32 *__cmsg, int __cmsg_len)
 {
 	struct cmsghdr32 * __ptr;
 
@@ -3541,7 +3633,7 @@
 	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
 	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
 	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
+
 	return err;
 }
 
@@ -3588,7 +3680,7 @@
  */
 static int
 cmsghdr_from_user32_to_kern(struct msghdr *kmsg, unsigned char *stackbuf,
-			    int stackbuf_size) 
+			    int stackbuf_size)
 {
 	struct cmsghdr32 *ucmsg;
 	struct cmsghdr *kcmsg, *kcmsg_base;
@@ -3812,7 +3904,7 @@
 		kcmsg32->cmsg_len = clen32;
 
 		ucmsg = (struct cmsghdr *) (((char *)ucmsg) +
-					    CMSG_ALIGN(clen64)); 
+					    CMSG_ALIGN(clen64));
 		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
 	}
 
@@ -3985,7 +4077,7 @@
 }
 
 extern asmlinkage long sys_init_module(const char *name_user,
-				      struct module *mod_user); 
+				      struct module *mod_user);
 
 /* Hey, when you're trying to init module, take time and prepare us a nice 64bit
  * module structure, even if from 32bit modutils... Why to pollute kernel... :))
@@ -4275,7 +4367,7 @@
 
 asmlinkage long
 sys32_query_module(char *name_user, int which, char *buf,
-		   __kernel_size_t32 bufsize, u32 ret) 
+		   __kernel_size_t32 bufsize, u32 ret)
 {
 	struct module *mod;
 	int err;
@@ -4340,7 +4432,7 @@
 	u32 value;
 	char name[60];
 };
-		 
+
 extern asmlinkage long sys_get_kernel_syms(struct kernel_sym *table);
 
 asmlinkage long
@@ -4349,7 +4441,7 @@
 	int len, i;
 	struct kernel_sym *tbl;
 	mm_segment_t old_fs;
-	
+
 	len = sys_get_kernel_syms(NULL);
 	if (!table) return len;
 	tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
@@ -4477,7 +4569,7 @@
 nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
 	int err;
-	
+
 	err = __get_user(karg->ca_version, &arg32->ca32_version);
 	err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
 	err |= __get_user(karg->ca_svc.svc_nthreads,
@@ -4489,7 +4581,7 @@
 nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
 	int err;
-	
+
 	err = __get_user(karg->ca_version, &arg32->ca32_version);
 	err |= copy_from_user(&karg->ca_client.cl_ident[0],
 			  &arg32->ca32_client.cl32_ident[0],
@@ -4513,7 +4605,7 @@
 nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
 	int err;
-	
+
 	err = __get_user(karg->ca_version, &arg32->ca32_version);
 	err |= copy_from_user(&karg->ca_export.ex_client[0],
 			  &arg32->ca32_export.ex32_client[0],
@@ -4589,7 +4681,7 @@
 nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
 	int err;
-	
+
 	err = __get_user(karg->ca_version, &arg32->ca32_version);
 	err |= copy_from_user(&karg->ca_getfh.gf_addr,
 			  &arg32->ca32_getfh.gf32_addr,
@@ -4607,7 +4699,7 @@
 nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
 {
 	int err;
-	
+
 	err = copy_to_user(&res32->cr32_getfh,
 			&kres->cr_getfh,
 			sizeof(res32->cr32_getfh));
@@ -4772,19 +4864,6 @@
 }
 
 
-extern asmlinkage long sys_newuname(struct new_utsname * name);
-
-asmlinkage long
-sys32_newuname(struct new_utsname * name)
-{
-	int ret = sys_newuname(name);
-	
-	if (current->personality == PER_LINUX32 && !ret) {
-		ret = copy_to_user(name->machine, "sparc\0\0", 8);
-	}
-	return ret;
-}
-
 extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
 				    size_t count, loff_t pos);
 
@@ -4825,7 +4904,7 @@
 }
 
 extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset,
-				       size_t count); 
+				       size_t count);
 
 asmlinkage long
 sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
@@ -4833,17 +4912,17 @@
 	mm_segment_t old_fs = get_fs();
 	int ret;
 	off_t of;
-	
+
 	if (offset && get_user(of, offset))
 		return -EFAULT;
-		
+
 	set_fs(KERNEL_DS);
 	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
 	set_fs(old_fs);
-	
+
 	if (!ret && offset && put_user(of, offset))
 		return -EFAULT;
-		
+
 	return ret;
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/Makefile linux/arch/ia64/kernel/Makefile
--- v2.4.3/linux/arch/ia64/kernel/Makefile	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/Makefile	Thu Apr  5 12:51:47 2001
@@ -11,19 +11,18 @@
 
 O_TARGET := kernel.o
 
-obj-y := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_ia64.o irq_sapic.o ivt.o \
+export-objs := ia64_ksyms.o
+
+obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o irq.o irq_ia64.o irq_sapic.o ivt.o \
 	 machvec.o pal.o process.o perfmon.o ptrace.o sal.o semaphore.o setup.o	\
 	 signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o
 obj-$(CONFIG_IA64_GENERIC) += machvec.o iosapic.o
 obj-$(CONFIG_IA64_DIG) += iosapic.o
 obj-$(CONFIG_IA64_PALINFO) += palinfo.o
+obj-$(CONFIG_IA64_EFIVARS) += efivars.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_SMP) += smp.o smpboot.o
 obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o
 obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
-
-export-objs := ia64_ksyms.o
-
-clean::
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/acpi.c linux/arch/ia64/kernel/acpi.c
--- v2.4.3/linux/arch/ia64/kernel/acpi.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/acpi.c	Thu Apr  5 12:51:47 2001
@@ -1,9 +1,9 @@
 /*
- * Advanced Configuration and Power Interface 
+ * Advanced Configuration and Power Interface
  *
- * Based on 'ACPI Specification 1.0b' February 2, 1999 and 
+ * Based on 'ACPI Specification 1.0b' February 2, 1999 and
  * 'IA-64 Extensions to ACPI Specification' Revision 0.6
- * 
+ *
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
  * Copyright (C) 2000 Hewlett-Packard Co.
@@ -111,15 +111,15 @@
  * Identify usable CPU's and remember them for SMP bringup later.
  */
 static void __init
-acpi20_lsapic (char *p) 
+acpi20_lsapic (char *p)
 {
 	int add = 1;
 
 	acpi20_entry_lsapic_t *lsapic = (acpi20_entry_lsapic_t *) p;
-	printk("      CPU %d (%.04x:%.04x): ", total_cpus, lsapic->eid, lsapic->id);
+	printk("      CPU %.04x:%.04x: ", lsapic->eid, lsapic->id);
 
 	if ((lsapic->flags & LSAPIC_ENABLED) == 0) {
-		printk("Disabled.\n");
+		printk("disabled.\n");
 		add = 0;
 	}
 
@@ -127,11 +127,14 @@
 	smp_boot_data.cpu_phys_id[total_cpus] = -1;
 #endif
 	if (add) {
-		printk("Available.\n");
 		available_cpus++;
+		printk("available");
 #ifdef CONFIG_SMP
 		smp_boot_data.cpu_phys_id[total_cpus] = (lsapic->id << 8) | lsapic->eid;
-#endif /* CONFIG_SMP */
+		if (hard_smp_processor_id() == smp_boot_data.cpu_phys_id[total_cpus])
+			printk(" (BSP)");
+#endif
+		printk(".\n");
 	}
 	total_cpus++;
 }
@@ -199,7 +202,7 @@
 			printk("ACPI 2.0 MADT: LOCAL SAPIC\n");
 			acpi20_lsapic(p);
 			break;
-	
+
 		case ACPI20_ENTRY_IO_SAPIC:
 			iosapic = (acpi_entry_iosapic_t *) p;
 			if (iosapic_init)
@@ -233,7 +236,7 @@
 	end = p + (madt->header.length - sizeof(acpi_madt_t));
 
 	while (p < end) {
-		
+
 		switch (*p) {
 		case ACPI20_ENTRY_INT_SRC_OVERRIDE:
 			printk("ACPI 2.0 MADT: INT SOURCE Override\n");
@@ -251,7 +254,7 @@
 		available_cpus, total_cpus);
 }
 
-int __init 
+int __init
 acpi20_parse (acpi20_rsdp_t *rsdp20)
 {
 	acpi_xsdt_t *xsdt;
@@ -311,12 +314,12 @@
 		printk("ACPI: Found 0 CPUS; assuming 1\n");
 		available_cpus = 1; /* We've got at least one of these, no? */
 	}
-	smp_boot_data.cpu_count = available_cpus;
+	smp_boot_data.cpu_count = total_cpus;
 #endif
 	return 1;
 }
 /*
- * ACPI 1.0b with 0.71 IA64 extensions functions; should be removed once all 
+ * ACPI 1.0b with 0.71 IA64 extensions functions; should be removed once all
  * platforms start supporting ACPI 2.0
  */
 
@@ -324,13 +327,13 @@
  * Identify usable CPU's and remember them for SMP bringup later.
  */
 static void __init
-acpi_lsapic (char *p) 
+acpi_lsapic (char *p)
 {
 	int add = 1;
 
 	acpi_entry_lsapic_t *lsapic = (acpi_entry_lsapic_t *) p;
 
-	if ((lsapic->flags & LSAPIC_PRESENT) == 0) 
+	if ((lsapic->flags & LSAPIC_PRESENT) == 0)
 		return;
 
 	printk("      CPU %d (%.04x:%.04x): ", total_cpus, lsapic->eid, lsapic->id);
@@ -388,7 +391,7 @@
 		      case ACPI_ENTRY_LOCAL_SAPIC:
 			acpi_lsapic(p);
 			break;
-	
+
 		      case ACPI_ENTRY_IO_SAPIC:
 			iosapic = (acpi_entry_iosapic_t *) p;
 			if (iosapic_init)
@@ -415,7 +418,7 @@
 	printk("      %d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
 }
 
-int __init 
+int __init
 acpi_parse (acpi_rsdp_t *rsdp)
 {
 	acpi_rsdt_t *rsdt;
@@ -433,9 +436,9 @@
 		return 0;
 	}
 
-	printk("ACPI: %.6s %.8s %d.%d\n", rsdt->header.oem_id, rsdt->header.oem_table_id, 
+	printk("ACPI: %.6s %.8s %d.%d\n", rsdt->header.oem_id, rsdt->header.oem_table_id,
 	       rsdt->header.oem_revision >> 16, rsdt->header.oem_revision & 0xffff);
-	
+
 #ifdef CONFIG_ACPI_KERNEL_CONFIG
 	acpi_cf_init(rsdp);
 #endif
@@ -460,7 +463,7 @@
 		printk("ACPI: Found 0 CPUS; assuming 1\n");
 		available_cpus = 1; /* We've got at least one of these, no? */
 	}
-	smp_boot_data.cpu_count = available_cpus;
+	smp_boot_data.cpu_count = total_cpus;
 #endif
 	return 1;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/brl_emu.c linux/arch/ia64/kernel/brl_emu.c
--- v2.4.3/linux/arch/ia64/kernel/brl_emu.c	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/kernel/brl_emu.c	Thu Apr  5 12:51:47 2001
@@ -1,6 +1,6 @@
 /*
  *  Emulation of the "brl" instruction for IA64 processors that
- *  don't support it in hardware. 
+ *  don't support it in hardware.
  *  Author: Stephan Zeisset, Intel Corp. <Stephan.Zeisset@intel.com>
  */
 
@@ -23,9 +23,9 @@
  *  of an and operation with the mask must be all 0's
  *  or all 1's for the address to be valid.
  */
-#define unimplemented_virtual_address(va) (					\
-	((va) & my_cpu_data.unimpl_va_mask) != 0 &&				\
-	((va) & my_cpu_data.unimpl_va_mask) != my_cpu_data.unimpl_va_mask	\
+#define unimplemented_virtual_address(va) (						\
+	((va) & local_cpu_data->unimpl_va_mask) != 0 &&					\
+	((va) & local_cpu_data->unimpl_va_mask) != local_cpu_data->unimpl_va_mask	\
 )
 
 /*
@@ -35,13 +35,13 @@
  *  address to be valid.
  */
 #define unimplemented_physical_address(pa) (		\
-	((pa) & my_cpu_data.unimpl_pa_mask) != 0	\
+	((pa) & local_cpu_data->unimpl_pa_mask) != 0	\
 )
 
 /*
- *  Handle an illegal operation fault that was caused by an 
+ *  Handle an illegal operation fault that was caused by an
  *  unimplemented "brl" instruction.
- *  If we are not successful (e.g because the illegal operation 
+ *  If we are not successful (e.g because the illegal operation
  *  wasn't caused by a "brl" after all), we return -1.
  *  If we are successful, we return either 0 or the address
  *  of a "fixup" function for manipulating preserved register
@@ -64,8 +64,8 @@
 	 *  Decode the instruction bundle.
 	 */
 
-        if (copy_from_user(bundle, (void *) (regs->cr_iip), sizeof(bundle)))
-                return rv; 
+	if (copy_from_user(bundle, (void *) (regs->cr_iip), sizeof(bundle)))
+		return rv;
 
 	next_ip = (unsigned long) regs->cr_iip + 16;
 
@@ -79,14 +79,14 @@
 	btype = ((bundle[1] >> 29) & 0x7);
 	qp = ((bundle[1] >> 23) & 0x3f);
 	offset = ((bundle[1] & 0x0800000000000000L) << 4)
-		| ((bundle[1] & 0x00fffff000000000L) >> 32) 
+		| ((bundle[1] & 0x00fffff000000000L) >> 32)
 		| ((bundle[1] & 0x00000000007fffffL) << 40)
 		| ((bundle[0] & 0xffff000000000000L) >> 24);
 
 	tmp_taken = regs->pr & (1L << qp);
 
 	switch(opcode) {
-		
+
 		case 0xC:
 			/*
 			 *  Long Branch.
@@ -169,7 +169,7 @@
 			 */
 			regs->cr_ifs = ((regs->cr_ifs & 0xffffffc00000007f)
 					- ((regs->cr_ifs >> 7) & 0x7f));
-				
+
 			break;
 
 		default:
@@ -180,7 +180,7 @@
 
 	}
 
-	regs->cr_iip += offset; 
+	regs->cr_iip += offset;
 	ia64_psr(regs)->ri = 0;
 
 	if (ia64_psr(regs)->it == 0)
@@ -188,7 +188,7 @@
 	else
 		unimplemented_address = unimplemented_virtual_address(regs->cr_iip);
 
-	if (unimplemented_address) { 
+	if (unimplemented_address) {
 		/*
 		 *  The target address contains unimplemented bits.
 		 */
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/efi.c linux/arch/ia64/kernel/efi.c
--- v2.4.3/linux/arch/ia64/kernel/efi.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/kernel/efi.c	Thu Apr 12 12:16:35 2001
@@ -5,9 +5,9 @@
  *
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999-2000 Hewlett-Packard Co.
+ * Copyright (C) 1999-2001 Hewlett-Packard Co.
  * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999-2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1999-2001 Stephane Eranian <eranian@hpl.hp.com>
  *
  * All EFI Runtime Services are not implemented yet as EFI only
  * supports physical mode addressing on SoftSDV. This is to be fixed
@@ -16,9 +16,8 @@
  * Implemented EFI runtime services and virtual mode calls.  --davidm
  *
  * Goutham Rao: <goutham.rao@intel.com>
- * 	Skip non-WB memory and ignore empty memory ranges.
+ *	Skip non-WB memory and ignore empty memory ranges.
  */
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -26,6 +25,7 @@
 
 #include <asm/efi.h>
 #include <asm/io.h>
+#include <asm/kregs.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 
@@ -128,9 +128,9 @@
 	efi_memory_desc_t *md;
 	u64 efi_desc_size, start, end;
 
-	efi_map_start = __va(ia64_boot_param.efi_memmap);
-	efi_map_end   = efi_map_start + ia64_boot_param.efi_memmap_size;
-	efi_desc_size = ia64_boot_param.efi_memdesc_size;
+	efi_map_start = __va(ia64_boot_param->efi_memmap);
+	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+	efi_desc_size = ia64_boot_param->efi_memdesc_size;
 
 	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 		md = p;
@@ -203,9 +203,9 @@
 	u64 mask, flags;
 	u64 vaddr;
 
-	efi_map_start = __va(ia64_boot_param.efi_memmap);
-	efi_map_end   = efi_map_start + ia64_boot_param.efi_memmap_size;
-	efi_desc_size = ia64_boot_param.efi_memdesc_size;
+	efi_map_start = __va(ia64_boot_param->efi_memmap);
+	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+	efi_desc_size = ia64_boot_param->efi_memdesc_size;
 
 	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 		md = p;
@@ -218,61 +218,48 @@
 			continue;
 		}
 		/*
-		 * We must use the same page size as the one used
-		 * for the kernel region when we map the PAL code.
-		 * This way, we avoid overlapping TRs if code is 
-		 * executed nearby. The Alt I-TLB installs 256MB
-		 * page sizes as defined for region 7.
+		 * The only ITLB entry in region 7 that is used is the one installed by
+		 * __start().  That entry covers a 64MB range.
 		 *
 		 * XXX Fixme: should be dynamic here (for page size)
 		 */
-		mask  = ~((1 << _PAGE_SIZE_256M)-1);
+		mask  = ~((1 << _PAGE_SIZE_64M) - 1);
 		vaddr = PAGE_OFFSET + md->phys_addr;
 
 		/*
-		 * We must check that the PAL mapping won't overlap
-		 * with the kernel mapping on ITR1. 
+		 * We must check that the PAL mapping won't overlap with the kernel
+		 * mapping.
 		 *
-		 * PAL code is guaranteed to be aligned on a power of 2
-		 * between 4k and 256KB.
-		 * Also from the documentation, it seems like there is an
-		 * implicit guarantee that you will need only ONE ITR to
-		 * map it. This implies that the PAL code is always aligned
-		 * on its size, i.e., the closest matching page size supported
-		 * by the TLB. Therefore PAL code is guaranteed never to cross
-		 * a 256MB unless it is bigger than 256MB (very unlikely!).
-		 * So for now the following test is enough to determine whether
-		 * or not we need a dedicated ITR for the PAL code.
+		 * PAL code is guaranteed to be aligned on a power of 2 between 4k and
+		 * 256KB.  Also from the documentation, it seems like there is an implicit
+		 * guarantee that you will need only ONE ITR to map it. This implies that
+		 * the PAL code is always aligned on its size, i.e., the closest matching
+		 * page size supported by the TLB. Therefore PAL code is guaranteed never
+		 * to cross a 64MB unless it is bigger than 64MB (very unlikely!).  So for
+		 * now the following test is enough to determine whether or not we need a
+		 * dedicated ITR for the PAL code.
 		 */
-		if ((vaddr & mask) == (PAGE_OFFSET & mask)) {
-			printk(__FUNCTION__ " : no need to install ITR for PAL Code\n");
+		if ((vaddr & mask) == (KERNEL_START & mask)) {
+			printk(__FUNCTION__ " : no need to install ITR for PAL code\n");
 			continue;
 		}
 
-	  	printk("CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
+		printk("CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
 		       smp_processor_id(), md->phys_addr, md->phys_addr + (md->num_pages << 12),
-		       vaddr & mask, (vaddr & mask) + 256*1024*1024);
+		       vaddr & mask, (vaddr & mask) + 64*1024*1024);
 
 		/*
 		 * Cannot write to CRx with PSR.ic=1
 		 */
 		ia64_clear_ic(flags);
-
-		/*
-		 * ITR0/DTR0: used for kernel code/data
-		 * ITR1/DTR1: used by HP simulator
-		 * ITR2/DTR2: map PAL code
-		 */
-		ia64_itr(0x1, 2, vaddr & mask,
-			 pte_val(mk_pte_phys(md->phys_addr,
-					     __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RX))),
-			 _PAGE_SIZE_256M);
+		ia64_itr(0x1, IA64_TR_PALCODE, vaddr & mask,
+			 pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL)), _PAGE_SIZE_64M);
 		local_irq_restore(flags);
-		ia64_srlz_i ();
+		ia64_srlz_i();
 	}
 }
 
-void __init 
+void __init
 efi_init (void)
 {
 	void *efi_map_start, *efi_map_end;
@@ -301,14 +288,14 @@
 	if (mem_limit != ~0UL)
 		printk("Ignoring memory above %luMB\n", mem_limit >> 20);
 
-	efi.systab = __va(ia64_boot_param.efi_systab);
+	efi.systab = __va(ia64_boot_param->efi_systab);
 
 	/*
 	 * Verify the EFI Table
- 	 */
-	if (efi.systab == NULL) 
+	 */
+	if (efi.systab == NULL)
 		panic("Woah! Can't find EFI system table.\n");
-	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) 
+	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
 		panic("Woah! EFI system table signature incorrect\n");
 	if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0)
 		printk("Warning: EFI system table major version mismatch: "
@@ -360,9 +347,9 @@
 	efi.get_next_high_mono_count = phys_get_next_high_mono_count;
 	efi.reset_system = phys_reset_system;
 
-	efi_map_start = __va(ia64_boot_param.efi_memmap);
-	efi_map_end   = efi_map_start + ia64_boot_param.efi_memmap_size;
-	efi_desc_size = ia64_boot_param.efi_memdesc_size;
+	efi_map_start = __va(ia64_boot_param->efi_memmap);
+	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+	efi_desc_size = ia64_boot_param->efi_memdesc_size;
 
 #if EFI_DEBUG
 	/* print EFI memory map: */
@@ -380,16 +367,7 @@
 #endif
 
 	efi_map_pal_code();
-
-#ifndef CONFIG_IA64_SOFTSDV_HACKS
-	/*
-	 * (Some) SoftSDVs seem to have a problem with this call.
-	 * Since it's mostly a performance optimization, just don't do
-	 * it for now...  --davidm 99/12/6
-	 */
 	efi_enter_virtual_mode();
-#endif
-
 }
 
 void
@@ -400,9 +378,9 @@
 	efi_status_t status;
 	u64 efi_desc_size;
 
-	efi_map_start = __va(ia64_boot_param.efi_memmap);
-	efi_map_end   = efi_map_start + ia64_boot_param.efi_memmap_size;
-	efi_desc_size = ia64_boot_param.efi_memdesc_size;
+	efi_map_start = __va(ia64_boot_param->efi_memmap);
+	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+	efi_desc_size = ia64_boot_param->efi_memdesc_size;
 
 	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 		md = p;
@@ -441,9 +419,9 @@
 	}
 
 	status = efi_call_phys(__va(runtime->set_virtual_address_map),
-			       ia64_boot_param.efi_memmap_size,
-			       efi_desc_size, ia64_boot_param.efi_memdesc_version,
-			       ia64_boot_param.efi_memmap);
+			       ia64_boot_param->efi_memmap_size,
+			       efi_desc_size, ia64_boot_param->efi_memdesc_version,
+			       ia64_boot_param->efi_memmap);
 	if (status != EFI_SUCCESS) {
 		printk("Warning: unable to switch EFI into virtual mode (status=%lu)\n", status);
 		return;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/efi_stub.S linux/arch/ia64/kernel/efi_stub.S
--- v2.4.3/linux/arch/ia64/kernel/efi_stub.S	Fri Jul 14 16:08:11 2000
+++ linux/arch/ia64/kernel/efi_stub.S	Thu Apr  5 12:51:47 2001
@@ -33,13 +33,6 @@
 #include <asm/processor.h>
 #include <asm/asmmacro.h>
 
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
-	.text
-
 /*
  * Inputs:
  *	in0 = address of function descriptor of EFI routine to call
@@ -50,15 +43,15 @@
  */
 
 GLOBAL_ENTRY(efi_call_phys)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
 	alloc loc1=ar.pfs,8,5,7,0
 	ld8 r2=[in0],8			// load EFI function's entry point
 	mov loc0=rp
-	UNW(.body)
+	.body
 	;;
 	mov loc2=gp			// save global pointer
 	mov loc4=ar.rsc			// save RSE configuration
-	mov ar.rsc=r0			// put RSE in enforced lazy, LE mode
+	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	;;
 
 	ld8 gp=[in0]			// load EFI function's global pointer
@@ -80,7 +73,7 @@
 	mov out5=in6
 	mov out6=in7
 	br.call.sptk.few rp=b6		// call the EFI function
-.ret1:	mov ar.rsc=r0			// put RSE in enforced lazy, LE mode
+.ret1:	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	mov r16=loc3
 	br.call.sptk.few rp=ia64_switch_mode // return to virtual mode
 .ret2:	mov ar.rsc=loc4			// restore RSE configuration
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/efivars.c linux/arch/ia64/kernel/efivars.c
--- v2.4.3/linux/arch/ia64/kernel/efivars.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/efivars.c	Thu Apr  5 12:51:47 2001
@@ -0,0 +1,433 @@
+/*
+ * EFI Variables - efivars.c
+ *
+ * Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@dell.com>
+ *
+ * This code takes all variables accessible from EFI runtime and
+ *  exports them via /proc
+ *
+ * Reads to /proc/efi/varname return an efi_variable_t structure.
+ * Writes to /proc/efi/varname must be an efi_variable_t structure.
+ * Writes with DataSize = 0 or Attributes = 0 deletes the variable.
+ * Writes with a new value in VariableName+VendorGuid creates
+ * a new variable.
+ *
+ *
+ *  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
+ *
+ * Changelog:
+ *
+ *  12 March 2001 - Matt Domsch <Matt_Domsch@dell.com>
+ *   Feedback received from Stephane Eranian incorporated.
+ *   efivar_write() checks copy_from_user() return value.
+ *   efivar_read/write() returns proper errno.
+ *   v0.02 release to linux-ia64@linuxia64.org
+ *
+ *  26 February 2001 - Matt Domsch <Matt_Domsch@dell.com>
+ *   v0.01 release to linux-ia64@linuxia64.org
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>		/* for capable() */
+#include <linux/mm.h>
+#include <linux/module.h>
+
+#include <asm/efi.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_SMP
+#include <linux/smp.h>
+#endif
+
+MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
+MODULE_DESCRIPTION("/proc interface to EFI Variables");
+
+#define EFIVARS_VERSION "0.02 2001-Mar-12"
+
+static int
+efivar_read(char *page, char **start, off_t off,
+	    int count, int *eof, void *data);
+static int
+efivar_write(struct file *file, const char *buffer,
+	     unsigned long count, void *data);
+
+
+/*
+ * The maximum size of VariableName + Data = 1024
+ * Therefore, it's reasonable to save that much
+ * space in each part of the structure,
+ * and we use a page for reading/writing.
+ */
+
+typedef struct _efi_variable_t {
+	efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
+	efi_guid_t    VendorGuid;
+	unsigned long DataSize;
+	__u8          Data[1024];
+	efi_status_t  Status;
+	__u32         Attributes;
+} __attribute__((packed)) efi_variable_t;
+
+
+typedef struct _efivar_entry_t {
+	efi_variable_t          var;
+	struct proc_dir_entry   *entry;
+	struct list_head        list;
+} efivar_entry_t;
+
+spinlock_t efivars_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(efivar_list);
+static struct proc_dir_entry *efi_dir = NULL;
+
+#define efivar_entry(n) list_entry(n, efivar_entry_t, list)
+
+/* Return the number of unicode characters in data */
+static unsigned long
+utf8_strlen(efi_char16_t *data, unsigned long maxlength)
+{
+	unsigned long length = 0;
+	while (*data++ != 0 && length < maxlength)
+		length++;
+	return length;
+}
+
+/* Return the number of bytes is the length of this string */
+/* Note: this is NOT the same as the number of unicode characters */
+static inline unsigned long
+utf8_strsize(efi_char16_t *data, unsigned long maxlength)
+{
+	return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) *
+		sizeof(efi_char16_t);
+}
+
+
+static int
+proc_calc_metrics(char *page, char **start, off_t off,
+		  int count, int *eof, int len)
+{
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+
+static void
+uuid_unparse(efi_guid_t *guid, char *out)
+{
+	sprintf(out, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		guid->data1, guid->data2, guid->data3,
+		guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3],
+		guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
+}
+
+
+
+
+
+/*
+ * efivar_create_proc_entry()
+ * Requires:
+ *    variable_name_size = number of bytes required to hold
+ *                         variable_name (not counting the NULL
+ *                         character at the end.
+ * Returns 1 on failure, 0 on success
+ */
+static int
+efivar_create_proc_entry(unsigned long variable_name_size,
+			 efi_char16_t *variable_name,
+			 efi_guid_t *vendor_guid)
+{
+
+	int i, short_name_size = variable_name_size /
+		sizeof(efi_char16_t) + 38;
+	char *short_name = kmalloc(short_name_size+1,
+				   GFP_KERNEL);
+	efivar_entry_t *new_efivar = kmalloc(sizeof(efivar_entry_t),
+					     GFP_KERNEL);
+	if (!short_name || !new_efivar)  {
+		if (short_name)        kfree(short_name);
+		if (new_efivar)        kfree(new_efivar);
+		return 1;
+	}
+	memset(short_name, 0, short_name_size+1);
+	memset(new_efivar, 0, sizeof(efivar_entry_t));
+
+	memcpy(new_efivar->var.VariableName, variable_name,
+	       variable_name_size);
+	memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t));
+
+	/* Convert Unicode to normal chars (assume top bits are 0),
+	   ala UTF-8 */
+	for (i=0; i<variable_name_size / sizeof(efi_char16_t); i++) {
+		short_name[i] = variable_name[i] & 0xFF;
+	}
+
+	/* This is ugly, but necessary to separate one vendor's
+	   private variables from another's.         */
+
+	*(short_name + strlen(short_name)) = '-';
+	uuid_unparse(vendor_guid, short_name + strlen(short_name));
+
+
+	/* Create the entry in proc */
+	new_efivar->entry = create_proc_entry(short_name, 0600, efi_dir);
+	kfree(short_name); short_name = NULL;
+	if (!new_efivar->entry) return 1;
+
+
+	new_efivar->entry->data = new_efivar;
+	new_efivar->entry->read_proc = efivar_read;
+	new_efivar->entry->write_proc = efivar_write;
+
+	list_add(&new_efivar->list, &efivar_list);
+
+
+	return 0;
+}
+
+
+
+/***********************************************************
+ * efivar_read()
+ * Requires:
+ * Modifies: page
+ * Returns: number of bytes written, or -EINVAL on failure
+ ***********************************************************/
+
+static int
+efivar_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	int len = sizeof(efi_variable_t);
+	efivar_entry_t *efi_var = data;
+	efi_variable_t *var_data = (efi_variable_t *)page;
+
+	if (!page || !data) return -EINVAL;
+
+	spin_lock(&efivars_lock);
+	MOD_INC_USE_COUNT;
+
+	memcpy(var_data, &efi_var->var, len);
+
+	var_data->DataSize = 1024;
+	var_data->Status = efi.get_variable(var_data->VariableName,
+					    &var_data->VendorGuid,
+					    &var_data->Attributes,
+					    &var_data->DataSize,
+					    var_data->Data);
+
+	MOD_DEC_USE_COUNT;
+	spin_unlock(&efivars_lock);
+
+	return proc_calc_metrics(page, start, off, count, eof, len);
+}
+
+/***********************************************************
+ * efivar_write()
+ * Requires: data is an efi_setvariable_t data type,
+ *           properly filled in, possibly by a call
+ *           first to efivar_read().
+ *           Caller must have CAP_SYS_ADMIN
+ * Modifies: NVRAM
+ * Returns: var_data->DataSize on success, errno on failure
+ *
+ ***********************************************************/
+static int
+efivar_write(struct file *file, const char *buffer,
+	     unsigned long count, void *data)
+{
+	unsigned long strsize1, strsize2;
+	int found=0;
+	struct list_head *pos;
+	unsigned long size = sizeof(efi_variable_t);
+	efi_status_t status;
+	efivar_entry_t *efivar = data, *search_efivar = NULL;
+	efi_variable_t *var_data;
+	if (!data || count != size) {
+		printk(KERN_WARNING "efivars: improper struct of size 0x%lx passed.\n", count);
+		return -EINVAL;
+	}
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	spin_lock(&efivars_lock);
+	MOD_INC_USE_COUNT;
+
+	var_data = kmalloc(size, GFP_KERNEL);
+	if (!var_data) {
+		MOD_DEC_USE_COUNT;
+		spin_unlock(&efivars_lock);
+		return -ENOMEM;
+	}
+	if (copy_from_user(var_data, buffer, size)) {
+		MOD_DEC_USE_COUNT;
+		spin_unlock(&efivars_lock);
+		return -EFAULT;
+	}
+
+
+	/* Since the data ptr we've currently got is probably for
+	   a different variable find the right variable.
+	   This allows any properly formatted data structure to
+	   be written to any of the files in /proc/efi and it will work.
+	*/
+	list_for_each(pos, &efivar_list) {
+		search_efivar = efivar_entry(pos);
+		strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
+		strsize2 = utf8_strsize(var_data->VariableName, 1024);
+		if ( strsize1 == strsize2 &&
+		     !memcmp(&(search_efivar->var.VariableName),
+			     var_data->VariableName, strsize1) &&
+		     !efi_guidcmp(search_efivar->var.VendorGuid,
+				  var_data->VendorGuid)) {
+			found = 1;
+			break;
+		}
+	}
+	if (found) efivar = search_efivar;
+
+	status = efi.set_variable(var_data->VariableName,
+				  &var_data->VendorGuid,
+				  var_data->Attributes,
+				  var_data->DataSize,
+				  var_data->Data);
+
+	if (status != EFI_SUCCESS) {
+		printk(KERN_WARNING "set_variable() failed: status=%lx\n", status);
+		kfree(var_data);
+		MOD_DEC_USE_COUNT;
+		spin_unlock(&efivars_lock);
+		return -EIO;
+	}
+
+
+	if (!var_data->DataSize || !var_data->Attributes) {
+		/* We just deleted the NVRAM variable */
+		remove_proc_entry(efivar->entry->name, efi_dir);
+		list_del(&efivar->list);
+		kfree(efivar);
+	}
+
+	/* If this is a new variable, set up the proc entry for it. */
+	if (!found) {
+		efivar_create_proc_entry(utf8_strsize(var_data->VariableName,
+						      1024),
+					 var_data->VariableName,
+					 &var_data->VendorGuid);
+	}
+
+	kfree(var_data);
+	MOD_DEC_USE_COUNT;
+	spin_unlock(&efivars_lock);
+	return size;
+}
+
+
+
+static int __init
+efivars_init(void)
+{
+
+	efi_status_t status;
+	efi_guid_t vendor_guid;
+	efi_char16_t *variable_name = kmalloc(1024, GFP_KERNEL);
+	unsigned long variable_name_size = 1024;
+
+	spin_lock(&efivars_lock);
+
+	printk(KERN_INFO "EFI Variables Facility v%s\n", EFIVARS_VERSION);
+
+	/* Per EFI spec, the maximum storage allocated for both
+	   the variable name and variable data is 1024 bytes.
+	*/
+
+	efi_dir = proc_mkdir("efi", NULL);
+
+	memset(variable_name, 0, 1024);
+
+	do {
+		variable_name_size=1024;
+
+		status = efi.get_next_variable(&variable_name_size,
+					       variable_name,
+					       &vendor_guid);
+
+
+		switch (status) {
+		case EFI_SUCCESS:
+			efivar_create_proc_entry(variable_name_size,
+						 variable_name,
+						 &vendor_guid);
+			break;
+		case EFI_NOT_FOUND:
+			break;
+		default:
+			printk(KERN_WARNING "get_next_variable: status=%lx\n", status);
+			status = EFI_NOT_FOUND;
+			break;
+		}
+
+	} while (status != EFI_NOT_FOUND);
+
+	kfree(variable_name);
+	spin_unlock(&efivars_lock);
+	return 0;
+}
+
+static void __exit
+efivars_exit(void)
+{
+	struct list_head *pos;
+	efivar_entry_t *efivar;
+
+	spin_lock(&efivars_lock);
+
+	list_for_each(pos, &efivar_list) {
+		efivar = efivar_entry(pos);
+		remove_proc_entry(efivar->entry->name, efi_dir);
+		list_del(&efivar->list);
+		kfree(efivar);
+	}
+	remove_proc_entry(efi_dir->name, NULL);
+	spin_unlock(&efivars_lock);
+
+}
+
+module_init(efivars_init);
+module_exit(efivars_exit);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/entry.S linux/arch/ia64/kernel/entry.S
--- v2.4.3/linux/arch/ia64/kernel/entry.S	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/entry.S	Thu Apr  5 12:51:47 2001
@@ -3,8 +3,8 @@
  *
  * Kernel entry points.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  * Copyright (C) 1999 Asit Mallick <Asit.K.Mallick@intel.com>
@@ -15,8 +15,6 @@
  * kernel stack. This allows us to handle interrupts without changing
  * to physical mode.
  *
- * ar.k4 is now used to hold last virtual map address
- * 
  * Jonathan Nickin	<nicklin@missioncriticallinux.com>
  * Patrick O'Rourke	<orourke@missioncriticallinux.com>
  * 11/07/2000
@@ -25,66 +23,84 @@
  * Global (preserved) predicate usage on syscall entry/exit path:
  *
  *	pKern:		See entry.h.
+ *	pUser:		See entry.h.
  *	pSys:		See entry.h.
  *	pNonSys:	!pSys
- *	p2:		(Alias of pKern!) True if any signals are pending.
  */
 
 #include <linux/config.h>
 
 #include <asm/cache.h>
 #include <asm/errno.h>
+#include <asm/kregs.h>
 #include <asm/offsets.h>
 #include <asm/processor.h>
 #include <asm/unistd.h>
 #include <asm/asmmacro.h>
 #include <asm/pgtable.h>
-	
-#include "entry.h"
 
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
+#include "minstate.h"
 
 	/*
 	 * execve() is special because in case of success, we need to
 	 * setup a null register window frame.
 	 */
 ENTRY(ia64_execve)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3)
 	alloc loc1=ar.pfs,3,2,4,0
 	mov loc0=rp
-	UNW(.body)
+	.body
 	mov out0=in0			// filename
 	;;				// stop bit between alloc and call
 	mov out1=in1			// argv
 	mov out2=in2			// envp
 	add out3=16,sp			// regs
 	br.call.sptk.few rp=sys_execve
-.ret0:	cmp4.ge p6,p0=r8,r0
+.ret0:	cmp4.ge p6,p7=r8,r0
 	mov ar.pfs=loc1			// restore ar.pfs
-	;;
-(p6)	mov ar.pfs=r0			// clear ar.pfs in case of success
 	sxt4 r8=r8			// return 64-bit result
+	;;
+	stf.spill [sp]=f0
+(p6)	cmp.ne pKern,pUser=r0,r0	// a successful execve() lands us in user-mode...
 	mov rp=loc0
+(p6)	mov ar.pfs=r0			// clear ar.pfs on success
+(p7)	br.ret.sptk.few rp
 
+	/*
+	 * In theory, we'd have to zap this state only to prevent leaking of
+	 * security sensitive state (e.g., if current->dumpable is zero).  However,
+	 * this executes in less than 20 cycles even on Itanium, so it's not worth
+	 * optimizing for...).
+	 */
+	mov r4=0;		mov f2=f0;		mov b1=r0
+	mov r5=0;		mov f3=f0;		mov b2=r0
+	mov r6=0;		mov f4=f0;		mov b3=r0
+	mov r7=0;		mov f5=f0;		mov b4=r0
+	mov ar.unat=0;		mov f10=f0;		mov b5=r0
+	ldf.fill f11=[sp];	ldf.fill f12=[sp];	mov f13=f0
+	ldf.fill f14=[sp];	ldf.fill f15=[sp];	mov f16=f0
+	ldf.fill f17=[sp];	ldf.fill f18=[sp];	mov f19=f0
+	ldf.fill f20=[sp];	ldf.fill f21=[sp];	mov f22=f0
+	ldf.fill f23=[sp];	ldf.fill f24=[sp];	mov f25=f0
+	ldf.fill f26=[sp];	ldf.fill f27=[sp];	mov f28=f0
+	ldf.fill f29=[sp];	ldf.fill f30=[sp];	mov f31=f0
+	mov ar.lc=0
 	br.ret.sptk.few rp
 END(ia64_execve)
 
 GLOBAL_ENTRY(sys_clone2)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
 	alloc r16=ar.pfs,3,2,4,0
 	DO_SAVE_SWITCH_STACK
 	mov loc0=rp
 	mov loc1=r16				// save ar.pfs across do_fork
-	UNW(.body)
+	.body
 	mov out1=in1
 	mov out3=in2
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
 	mov out0=in0				// out0 = clone_flags
 	br.call.sptk.few rp=do_fork
-.ret1:	UNW(.restore sp)
+.ret1:	.restore sp
 	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop the switch stack
 	mov ar.pfs=loc1
 	mov rp=loc0
@@ -92,43 +108,42 @@
 END(sys_clone2)
 
 GLOBAL_ENTRY(sys_clone)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
 	alloc r16=ar.pfs,2,2,4,0
 	DO_SAVE_SWITCH_STACK
 	mov loc0=rp
 	mov loc1=r16				// save ar.pfs across do_fork
-	UNW(.body)
+	.body
 	mov out1=in1
 	mov out3=0
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
 	mov out0=in0				// out0 = clone_flags
 	br.call.sptk.few rp=do_fork
-.ret2:	UNW(.restore sp)
+.ret2:	.restore sp
 	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop the switch stack
 	mov ar.pfs=loc1
 	mov rp=loc0
 	br.ret.sptk.many rp
 END(sys_clone)
 
-#define KSTACK_TR	2
-
 /*
  * prev_task <- ia64_switch_to(struct task_struct *next)
  */
 GLOBAL_ENTRY(ia64_switch_to)
-	UNW(.prologue)
+	.prologue
 	alloc r16=ar.pfs,1,0,0,0
 	DO_SAVE_SWITCH_STACK
-	UNW(.body)
+	.body
 
 	adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13
-	mov r27=ar.k4
+	mov r27=IA64_KR(CURRENT_STACK)
 	dep r20=0,in0,61,3		// physical address of "current"
 	;;
 	st8 [r22]=sp			// save kernel stack pointer of old task
-	shr.u r26=r20,_PAGE_SIZE_256M
+	shr.u r26=r20,_PAGE_SIZE_64M
+	mov r16=1
 	;;
-	cmp.eq p7,p6=r26,r0		// check < 256M
+	cmp.ne p6,p7=r26,r16		// check >= 64M && < 128M
 	adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
 	;;
 	/*
@@ -142,50 +157,36 @@
 (p6)	ssm psr.ic			// if we we had to map, renable the psr.ic bit FIRST!!!
 	;;
 (p6)	srlz.d
-	mov ar.k6=r20			// copy "current" into ar.k6
+	mov IA64_KR(CURRENT)=r20	// update "current" application register
 	mov r8=r13			// return pointer to previously running task
 	mov r13=in0			// set "current" pointer
 	;;
 (p6)	ssm psr.i			// renable psr.i AFTER the ic bit is serialized
-	DO_LOAD_SWITCH_STACK( )
+	DO_LOAD_SWITCH_STACK
 
 #ifdef CONFIG_SMP
 	sync.i				// ensure "fc"s done by this CPU are visible on other CPUs
-#endif 
+#endif
 	br.ret.sptk.few rp		// boogie on out in new context
 
 .map:
 	rsm psr.i | psr.ic
-	movl r25=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX
+	movl r25=PAGE_KERNEL
 	;;
 	srlz.d
 	or r23=r25,r20			// construct PA | page properties
-	mov r25=_PAGE_SIZE_256M<<2
+	mov r25=_PAGE_SIZE_64M<<2
 	;;
 	mov cr.itir=r25
 	mov cr.ifa=in0			// VA of next task...
 	;;
-	mov r25=KSTACK_TR		// use tr entry #2...
-	mov ar.k4=r26			// remember last page we mapped...
+	mov r25=IA64_TR_CURRENT_STACK
+	mov IA64_KR(CURRENT_STACK)=r26	// remember last page we mapped...
 	;;
 	itr.d dtr[r25]=r23		// wire in new mapping...
 	br.cond.sptk.many .done
-	;;
 END(ia64_switch_to)
 
-#ifndef CONFIG_IA64_NEW_UNWIND
-	/*
-	 * Like save_switch_stack, but also save the stack frame that is active
-	 * at the time this function is called.
-	 */
-ENTRY(save_switch_stack_with_current_frame)
-	UNW(.prologue)
-	alloc r16=ar.pfs,0,0,0,0		// pass ar.pfs to save_switch_stack
-	DO_SAVE_SWITCH_STACK
-	br.ret.sptk.few rp
-END(save_switch_stack_with_current_frame)
-#endif /* !CONFIG_IA64_NEW_UNWIND */
-
 /*
  * Note that interrupts are enabled during save_switch_stack and
  * load_switch_stack.  This means that we may get an interrupt with
@@ -205,95 +206,108 @@
  *	- rp (b0) holds return address to save
  */
 GLOBAL_ENTRY(save_switch_stack)
-	UNW(.prologue)
-	UNW(.altrp b7)
+	.prologue
+	.altrp b7
 	flushrs			// flush dirty regs to backing store (must be first in insn group)
+	.save @priunat,r17
 	mov r17=ar.unat		// preserve caller's
-	adds r2=16,sp		// r2 = &sw->caller_unat
+	.body
+#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) \
+      || defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
+	adds r3=80,sp
 	;;
-	mov r18=ar.fpsr		// preserve fpsr
-	mov ar.rsc=r0		// put RSE in mode: enforced lazy, little endian, pl 0
+	lfetch.fault.excl.nt1 [r3],128
+#endif
+	mov ar.rsc=0		// put RSE in mode: enforced lazy, little endian, pl 0
+#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) \
+      || defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
+	adds r2=16+128,sp
 	;;
-	mov r19=ar.rnat
-	adds r3=24,sp		// r3 = &sw->ar_fpsr
+	lfetch.fault.excl.nt1 [r2],128
+	lfetch.fault.excl.nt1 [r3],128
+#endif
+	adds r14=SW(R4)+16,sp
+#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) \
+      || defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
+	;;
+	lfetch.fault.excl [r2]
+	lfetch.fault.excl [r3]
+#endif
+	adds r15=SW(R5)+16,sp
 	;;
-	.savesp ar.unat,SW(CALLER_UNAT)
-	st8 [r2]=r17,16
-	.savesp ar.fpsr,SW(AR_FPSR)
-	st8 [r3]=r18,24
+	mov r18=ar.fpsr		// preserve fpsr
+	mov r19=ar.rnat
+	add r2=SW(F2)+16,sp	// r2 = &sw->f2
+.mem.offset 0,0; st8.spill [r14]=r4,16		// spill r4
+.mem.offset 8,0; st8.spill [r15]=r5,16		// spill r5
+	add r3=SW(F3)+16,sp	// r3 = &sw->f3
 	;;
-	UNW(.body)
 	stf.spill [r2]=f2,32
 	stf.spill [r3]=f3,32
 	mov r21=b0
+.mem.offset 0,0; st8.spill [r14]=r6,16		// spill r6
+.mem.offset 8,0; st8.spill [r15]=r7,16		// spill r7
+	mov r22=b1
 	;;
+	// since we're done with the spills, read and save ar.unat:
+	mov r29=ar.unat		// M-unit
+	mov r20=ar.bspstore	// M-unit
+	mov r23=b2
 	stf.spill [r2]=f4,32
 	stf.spill [r3]=f5,32
+	mov r24=b3
 	;;
+	st8 [r14]=r21,16	// save b0
+	st8 [r15]=r22,16	// save b1
+	mov r25=b4
 	stf.spill [r2]=f10,32
 	stf.spill [r3]=f11,32
-	mov r22=b1
+	mov r26=b5
 	;;
+	st8 [r14]=r23,16	// save b2
+	st8 [r15]=r24,16	// save b3
+	mov r21=ar.lc		// I-unit
 	stf.spill [r2]=f12,32
 	stf.spill [r3]=f13,32
-	mov r23=b2
 	;;
+	st8 [r14]=r25,16	// save b4
+	st8 [r15]=r26,16	// save b5
 	stf.spill [r2]=f14,32
 	stf.spill [r3]=f15,32
-	mov r24=b3
 	;;
+	st8 [r14]=r16		// save ar.pfs
+	st8 [r15]=r21		// save ar.lc
 	stf.spill [r2]=f16,32
 	stf.spill [r3]=f17,32
-	mov r25=b4
 	;;
 	stf.spill [r2]=f18,32
 	stf.spill [r3]=f19,32
-	mov r26=b5
 	;;
 	stf.spill [r2]=f20,32
 	stf.spill [r3]=f21,32
-	mov r17=ar.lc				// I-unit
 	;;
 	stf.spill [r2]=f22,32
 	stf.spill [r3]=f23,32
 	;;
 	stf.spill [r2]=f24,32
 	stf.spill [r3]=f25,32
+	add r14=SW(CALLER_UNAT)+16,sp
 	;;
 	stf.spill [r2]=f26,32
 	stf.spill [r3]=f27,32
+	add r15=SW(AR_FPSR)+16,sp
 	;;
 	stf.spill [r2]=f28,32
 	stf.spill [r3]=f29,32
-	;;
-	stf.spill [r2]=f30,32
-	stf.spill [r3]=f31,24
-	;;
-.mem.offset 0,0;	st8.spill [r2]=r4,16
-.mem.offset 8,0;	st8.spill [r3]=r5,16
-	;;
-.mem.offset 0,0;	st8.spill [r2]=r6,16
-.mem.offset 8,0;	st8.spill [r3]=r7,16
-	;;
-	st8 [r2]=r21,16		// save b0
-	st8 [r3]=r22,16		// save b1
-	/* since we're done with the spills, read and save ar.unat: */
-	mov r18=ar.unat		// M-unit
-	mov r20=ar.bspstore	// M-unit
-	;;
-	st8 [r2]=r23,16		// save b2
-	st8 [r3]=r24,16		// save b3
-	;;
-	st8 [r2]=r25,16		// save b4
-	st8 [r3]=r26,16		// save b5
-	;;
-	st8 [r2]=r16,16		// save ar.pfs
-	st8 [r3]=r17,16		// save ar.lc
+	st8 [r14]=r17		// save caller_unat
+	st8 [r15]=r18		// save fpsr
 	mov r21=pr
 	;;
-	st8 [r2]=r18,16		// save ar.unat
+	stf.spill [r2]=f30,(SW(AR_UNAT)-SW(F30))
+	stf.spill [r3]=f31,(SW(AR_RNAT)-SW(F31))
+	;;
+	st8 [r2]=r29,16		// save ar.unat
 	st8 [r3]=r19,16		// save ar.rnat
-	mov b7=r28
 	;;
 	st8 [r2]=r20		// save ar.bspstore
 	st8 [r3]=r21		// save predicate registers
@@ -303,16 +317,27 @@
 
 /*
  * load_switch_stack:
+ *	- "invala" MUST be done at call site (normally in DO_LOAD_SWITCH_STACK)
  *	- b7 holds address to return to
+ *	- must not touch r8-r11
  */
 ENTRY(load_switch_stack)
-	UNW(.prologue)
-	UNW(.altrp b7)
-	invala			// invalidate ALAT
-	UNW(.body)
-	adds r2=IA64_SWITCH_STACK_B0_OFFSET+16,sp	// get pointer to switch_stack.b0
-	mov ar.rsc=r0		// put RSE into enforced lazy mode
-	adds r3=IA64_SWITCH_STACK_B0_OFFSET+24,sp	// get pointer to switch_stack.b1
+	.prologue
+	.altrp b7
+	.body
+#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) \
+      || defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
+
+	lfetch.fault.nt1 [sp]
+#endif
+	adds r2=SW(AR_BSPSTORE)+16,sp
+	adds r3=SW(AR_UNAT)+16,sp
+	mov ar.rsc=0						// put RSE into enforced lazy mode
+	adds r14=SW(CALLER_UNAT)+16,sp
+	adds r15=SW(AR_FPSR)+16,sp
+	;;
+	ld8 r27=[r2],(SW(B0)-SW(AR_BSPSTORE))	// bspstore
+	ld8 r29=[r3],(SW(B1)-SW(AR_UNAT))	// unat
 	;;
 	ld8 r21=[r2],16		// restore b0
 	ld8 r22=[r3],16		// restore b1
@@ -323,84 +348,77 @@
 	ld8 r25=[r2],16		// restore b4
 	ld8 r26=[r3],16		// restore b5
 	;;
-	ld8 r16=[r2],16		// restore ar.pfs
-	ld8 r17=[r3],16		// restore ar.lc
+	ld8 r16=[r2],(SW(PR)-SW(AR_PFS))	// ar.pfs
+	ld8 r17=[r3],(SW(AR_RNAT)-SW(AR_LC))	// ar.lc
 	;;
-	ld8 r18=[r2],16		// restore ar.unat
-	ld8 r19=[r3],16		// restore ar.rnat
-	mov b0=r21
+	ld8 r28=[r2]		// restore pr
+	ld8 r30=[r3]		// restore rnat
 	;;
-	ld8 r20=[r2]		// restore ar.bspstore
-	ld8 r21=[r3]		// restore predicate registers
-	mov ar.pfs=r16
+	ld8 r18=[r14],16	// restore caller's unat
+	ld8 r19=[r15],24	// restore fpsr
 	;;
-	mov ar.bspstore=r20
+	ldf.fill f2=[r14],32
+	ldf.fill f3=[r15],32
 	;;
-	loadrs			// invalidate stacked regs outside current frame
-	adds r2=16-IA64_SWITCH_STACK_SIZE,r2	// get pointer to switch_stack.caller_unat
-	;;			// stop bit for rnat dependency
-	mov ar.rnat=r19
-	mov ar.unat=r18		// establish unat holding the NaT bits for r4-r7
-	adds r3=16-IA64_SWITCH_STACK_SIZE,r3	// get pointer to switch_stack.ar_fpsr
+	ldf.fill f4=[r14],32
+	ldf.fill f5=[r15],32
 	;;
-	ld8 r18=[r2],16		// restore caller's unat
-	ld8 r19=[r3],24		// restore fpsr
-	mov ar.lc=r17
+	ldf.fill f10=[r14],32
+	ldf.fill f11=[r15],32
+	;;
+	ldf.fill f12=[r14],32
+	ldf.fill f13=[r15],32
 	;;
-	ldf.fill f2=[r2],32
-	ldf.fill f3=[r3],32
-	mov pr=r21,-1
+	ldf.fill f14=[r14],32
+	ldf.fill f15=[r15],32
 	;;
-	ldf.fill f4=[r2],32
-	ldf.fill f5=[r3],32
+	ldf.fill f16=[r14],32
+	ldf.fill f17=[r15],32
 	;;
-	ldf.fill f10=[r2],32
-	ldf.fill f11=[r3],32
+	ldf.fill f18=[r14],32
+	ldf.fill f19=[r15],32
+	mov b0=r21
+	;;
+	ldf.fill f20=[r14],32
+	ldf.fill f21=[r15],32
 	mov b1=r22
 	;;
-	ldf.fill f12=[r2],32
-	ldf.fill f13=[r3],32
+	ldf.fill f22=[r14],32
+	ldf.fill f23=[r15],32
 	mov b2=r23
 	;;
-	ldf.fill f14=[r2],32
-	ldf.fill f15=[r3],32
+	mov ar.bspstore=r27
+	mov ar.unat=r29		// establish unat holding the NaT bits for r4-r7
 	mov b3=r24
 	;;
-	ldf.fill f16=[r2],32
-	ldf.fill f17=[r3],32
+	ldf.fill f24=[r14],32
+	ldf.fill f25=[r15],32
 	mov b4=r25
 	;;
-	ldf.fill f18=[r2],32
-	ldf.fill f19=[r3],32
+	ldf.fill f26=[r14],32
+	ldf.fill f27=[r15],32
 	mov b5=r26
 	;;
-	ldf.fill f20=[r2],32
-	ldf.fill f21=[r3],32
-	;;
-	ldf.fill f22=[r2],32
-	ldf.fill f23=[r3],32
-	;;
-	ldf.fill f24=[r2],32
-	ldf.fill f25=[r3],32
-	;;
-	ldf.fill f26=[r2],32
-	ldf.fill f27=[r3],32
-	;;
-	ldf.fill f28=[r2],32
-	ldf.fill f29=[r3],32
+	ldf.fill f28=[r14],32
+	ldf.fill f29=[r15],32
+	mov ar.pfs=r16
 	;;
-	ldf.fill f30=[r2],32
-	ldf.fill f31=[r3],24
+	ldf.fill f30=[r14],32
+	ldf.fill f31=[r15],24
+	mov ar.lc=r17
 	;;
-	ld8.fill r4=[r2],16
-	ld8.fill r5=[r3],16
+	ld8.fill r4=[r14],16
+	ld8.fill r5=[r15],16
+	mov pr=r28,-1
 	;;
-	ld8.fill r6=[r2],16
-	ld8.fill r7=[r3],16
+	ld8.fill r6=[r14],16
+	ld8.fill r7=[r15],16
+
 	mov ar.unat=r18				// restore caller's unat
+	mov ar.rnat=r30				// must restore after bspstore but before rsc!
 	mov ar.fpsr=r19				// restore fpsr
 	mov ar.rsc=3				// put RSE back into eager mode, pl 0
-	br.cond.sptk.few b7
+	br.cond.sptk.many b7
 END(load_switch_stack)
 
 GLOBAL_ENTRY(__ia64_syscall)
@@ -415,17 +433,16 @@
 	br.ret.sptk.few rp
 END(__ia64_syscall)
 
-	//
-	// We invoke syscall_trace through this intermediate function to
-	// ensure that the syscall input arguments are not clobbered.  We
-	// also use it to preserve b6, which contains the syscall entry point.
-	//
+	/*
+	 * We invoke syscall_trace through this intermediate function to
+	 * ensure that the syscall input arguments are not clobbered.  We
+	 * also use it to preserve b6, which contains the syscall entry point.
+	 */
 GLOBAL_ENTRY(invoke_syscall_trace)
-#ifdef CONFIG_IA64_NEW_UNWIND
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
 	alloc loc1=ar.pfs,8,3,0,0
 	mov loc0=rp
-	UNW(.body)
+	.body
 	mov loc2=b6
 	;;
 	br.call.sptk.few rp=syscall_trace
@@ -433,33 +450,18 @@
 	mov ar.pfs=loc1
 	mov b6=loc2
 	br.ret.sptk.few rp
-#else /* !CONFIG_IA64_NEW_SYSCALL */
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8))
-	alloc loc1=ar.pfs,8,3,0,0
-	;;			// WAW on CFM at the br.call
-	mov loc0=rp
-	br.call.sptk.many rp=save_switch_stack_with_current_frame	// must preserve b6!!
-.ret4:	mov loc2=b6
-	br.call.sptk.few rp=syscall_trace
-.ret5:	adds sp=IA64_SWITCH_STACK_SIZE,sp	// drop switch_stack frame
-	mov rp=loc0
-	mov ar.pfs=loc1
-	mov b6=loc2
-	;;
-	br.ret.sptk.few rp
-#endif /* !CONFIG_IA64_NEW_SYSCALL */
 END(invoke_syscall_trace)
 
-	//
-	// Invoke a system call, but do some tracing before and after the call.
-	// We MUST preserve the current register frame throughout this routine
-	// because some system calls (such as ia64_execve) directly
-	// manipulate ar.pfs.
-	//
-	// Input:
-	//	r15 = syscall number
-	//	b6  = syscall entry point
-	//
+	/*
+	 * Invoke a system call, but do some tracing before and after the call.
+	 * We MUST preserve the current register frame throughout this routine
+	 * because some system calls (such as ia64_execve) directly
+	 * manipulate ar.pfs.
+	 *
+	 * Input:
+	 *	r15 = syscall number
+	 *	b6  = syscall entry point
+	 */
 	.global ia64_strace_leave_kernel
 
 GLOBAL_ENTRY(ia64_trace_syscall)
@@ -468,8 +470,8 @@
 .ret6:	br.call.sptk.few rp=b6			// do the syscall
 strace_check_retval:
 	cmp.lt p6,p0=r8,r0			// syscall failed?
-	adds r2=IA64_PT_REGS_R8_OFFSET+16,sp	// r2 = &pt_regs.r8
-	adds r3=IA64_PT_REGS_R8_OFFSET+32,sp	// r3 = &pt_regs.r10
+	adds r2=PT(R8)+16,sp			// r2 = &pt_regs.r8
+	adds r3=PT(R10)+16,sp			// r3 = &pt_regs.r10
 	mov r10=0
 (p6)	br.cond.sptk.few strace_error		// syscall failed ->
 	;;					// avoid RAW on r10
@@ -492,28 +494,14 @@
 	br.cond.sptk.few strace_save_retval
 END(ia64_trace_syscall)
 
-/*
- * A couple of convenience macros to help implement/understand the state
- * restoration that happens at the end of ia64_ret_from_syscall.
- */
-#define rARPR		r31
-#define rCRIFS		r30
-#define rCRIPSR		r29
-#define rCRIIP		r28
-#define rARRSC		r27
-#define rARPFS		r26
-#define rARUNAT		r25
-#define rARRNAT		r24
-#define rARBSPSTORE	r23
-#define rKRBS		r22
-#define rB6		r21
-
 GLOBAL_ENTRY(ia64_ret_from_clone)
 	PT_REGS_UNWIND_INFO(0)
 #ifdef CONFIG_SMP
-	// In SMP mode, we need to call schedule_tail to complete the scheduling process.
-	// Called by ia64_switch_to after do_fork()->copy_thread().  r8 contains the
-	// address of the previously executing task.
+	/*
+	 * In SMP mode, we need to call invoke_schedule_tail to complete the scheduling process.
+	 * Called by ia64_switch_to after do_fork()->copy_thread().  r8 contains the
+	 * address of the previously executing task.
+	 */
 	br.call.sptk.few rp=invoke_schedule_tail
 .ret8:
 #endif
@@ -530,8 +518,8 @@
 GLOBAL_ENTRY(ia64_ret_from_syscall)
 	PT_REGS_UNWIND_INFO(0)
 	cmp.ge p6,p7=r8,r0			// syscall executed successfully?
-	adds r2=IA64_PT_REGS_R8_OFFSET+16,sp	// r2 = &pt_regs.r8
-	adds r3=IA64_PT_REGS_R8_OFFSET+32,sp	// r3 = &pt_regs.r10
+	adds r2=PT(R8)+16,sp			// r2 = &pt_regs.r8
+	adds r3=PT(R10)+16,sp			// r3 = &pt_regs.r10
 	;;
 	.mem.offset 0,0
 (p6)	st8.spill [r2]=r8	// store return value in slot for r8 and set unat bit
@@ -541,78 +529,57 @@
 END(ia64_ret_from_syscall)
 	// fall through
 GLOBAL_ENTRY(ia64_leave_kernel)
-	// check & deliver software interrupts:
-
 	PT_REGS_UNWIND_INFO(0)
-#ifdef CONFIG_SMP
-	adds r2=IA64_TASK_PROCESSOR_OFFSET,r13
-	movl r3=irq_stat		// softirq_active
-	;;
-	ld4 r2=[r2]
+	cmp.eq p16,p0=r0,r0			// set the "first_time" flag
+	movl r15=PERCPU_ADDR+IA64_CPU_SOFTIRQ_ACTIVE_OFFSET  // r15 = &cpu_data.softirq.active
 	;;
-	shl r2=r2,SMP_CACHE_SHIFT	// can't use shladd here...
+	ld8 r2=[r15]
+	movl r14=.restart
 	;;
-	add r3=r2,r3
-#else
-	movl r3=irq_stat		// softirq_active
+	lfetch.fault [sp]
+	shr.u r3=r2,32			// r3 = cpu_data.softirq.mask
+	MOVBR(.ret.sptk,rp,r14,.restart)
+.restart:
+	adds r17=IA64_TASK_NEED_RESCHED_OFFSET,r13
+	adds r18=IA64_TASK_SIGPENDING_OFFSET,r13
+#ifdef CONFIG_PERFMON
+	adds r19=IA64_TASK_PFM_NOTIFY_OFFSET,r13
 #endif
 	;;
-	ld8 r2=[r3]		// r3 (softirq_active+softirq_mask) is guaranteed to be 8-byte aligned!
-	;;
-	shr r3=r2,32
+	ld8 r17=[r17]				// load current->need_resched
+	ld4 r18=[r18]				// load current->sigpending
+(p16)	and r2=r2,r3				// r2 <- (softirq.active & softirq.mask)
 	;;
-	and r2=r2,r3
+#ifdef CONFIG_PERFMON
+	ld8 r19=[r19]				// load current->task.pfm_notify
+#endif
+(p16)	cmp4.ne.unc p6,p0=r2,r0			// p6 <- (softirq.active & softirq.mask) != 0
+(pUser)	cmp.ne.unc p7,p0=r17,r0			// current->need_resched != 0?
 	;;
-	cmp4.ne p6,p7=r2,r0
-(p6)	br.call.spnt.many rp=invoke_do_softirq
-1:
-(pKern)	br.cond.dpnt.many restore_all	// yup -> skip check for rescheduling & signal delivery
-
-	// call schedule() until we find a task that doesn't have need_resched set:
-
-back_from_resched:
-	{ .mii
-	  adds r2=IA64_TASK_NEED_RESCHED_OFFSET,r13
-	  mov r3=ip
-	  adds r14=IA64_TASK_SIGPENDING_OFFSET,r13
-	}
+(pUser)	cmp.ne.unc p8,p0=r18,r0			// current->sigpending != 0?
+#ifdef CONFIG_PERFMON
+	cmp.ne p9,p0=r19,r0			// current->task.pfm_notify != 0?
+#endif
+	cmp.ne p16,p0=r0,r0			// clear the "first_time" flag
 	;;
-	ld8 r2=[r2]
-	ld4 r14=[r14]
-	mov rp=r3			// arrange for schedule() to return to back_from_resched
+# if __GNUC__ < 3
+(p6)	br.call.spnt.many b7=invoke_do_softirq
+# else
+(p6)	br.call.spnt.many b7=do_softirq
+# endif
+#ifdef CONFIG_PERFMON
+(p9)	br.call.spnt.many b7=pfm_overflow_notify
+#endif
+# if __GNUC__ < 3
+(p7)	br.call.spnt.many b7=invoke_schedule
+#else
+(p7)	br.call.spnt.many b7=schedule
+#endif
+	adds r2=PT(R8)+16,r12
+	adds r3=PT(R9)+16,r12
+(p8)	br.call.spnt.many b7=handle_signal_delivery	// check & deliver pending signals
 	;;
-	cmp.ne p6,p0=r2,r0
-	cmp.ne p2,p0=r14,r0		// NOTE: pKern is an alias for p2!!
-	srlz.d
-(p6)	br.call.spnt.many b6=invoke_schedule	// ignore return value
-2:
-	// check & deliver pending signals:
-(p2)	br.call.spnt.few rp=handle_signal_delivery
-.ret9:
-#ifdef CONFIG_IA64_SOFTSDV_HACKS
-	// Check for lost ticks
-	rsm psr.i
-	mov r2 = ar.itc
-	movl r14 = 1000			// latency tolerance
-	mov r3 = cr.itm
-	;;
-	sub r2 = r2, r3
-	;;
-	sub r2 = r2, r14
-	;;
-	cmp.ge p6,p7 = r2, r0
-(p6)	br.call.spnt.few rp=invoke_ia64_reset_itm
-.ret10:
-	;;
-	ssm psr.i
-#endif 
-restore_all:
-
 	// start restoring the state saved on the kernel stack (struct pt_regs):
-
-	adds r2=IA64_PT_REGS_R8_OFFSET+16,r12
-	adds r3=IA64_PT_REGS_R8_OFFSET+24,r12
-	;;
 	ld8.fill r8=[r2],16
 	ld8.fill r9=[r3],16
 	;;
@@ -643,6 +610,9 @@
 	ld8.fill r30=[r2],16
 	ld8.fill r31=[r3],16
 	;;
+	rsm psr.i | psr.ic	// initiate turning off of interrupts & interruption collection
+	invala			// invalidate ALAT
+	;;
 	ld8 r1=[r2],16		// ar.ccv
 	ld8 r13=[r3],16		// ar.fpsr
 	;;
@@ -658,14 +628,11 @@
 	mov ar.ccv=r1
 	mov ar.fpsr=r13
 	mov b0=r14
-	// turn off interrupts, interrupt collection
-	rsm psr.i | psr.ic
 	;;
-	srlz.i			// EAS 2.5
+	srlz.i			// ensure interrupts & interruption collection are off
 	mov b7=r15
 	;;
-	invala			// invalidate ALAT
-	bsw.0;;			// switch back to bank 0 (must be last in insn group)
+	bsw.0			// switch back to bank 0
 	;;
 #ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
 	nop.i 0x0
@@ -683,17 +650,18 @@
 	;;
 	ld8 rCRIFS=[r16],16	// load cr.ifs
 	ld8 rARUNAT=[r17],16	// load ar.unat
+	cmp.eq p9,p0=r0,r0	// set p9 to indicate that we should restore cr.ifs
 	;;
 	ld8 rARPFS=[r16],16	// load ar.pfs
 	ld8 rARRSC=[r17],16	// load ar.rsc
 	;;
 	ld8 rARRNAT=[r16],16	// load ar.rnat (may be garbage)
-	ld8 rARBSPSTORE=[r17],16	// load ar.bspstore (may be garbage)
+	ld8 rARBSPSTORE=[r17],16 // load ar.bspstore (may be garbage)
 	;;
 	ld8 rARPR=[r16],16	// load predicates
 	ld8 rB6=[r17],16	// load b6
 	;;
-	ld8 r18=[r16],16	// load ar.rsc value for "loadrs"
+	ld8 r19=[r16],16	// load ar.rsc value for "loadrs"
 	ld8.fill r1=[r17],16	// load r1
 	;;
 	ld8.fill r2=[r16],16
@@ -701,62 +669,102 @@
 	;;
 	ld8.fill r12=[r16],16
 	ld8.fill r13=[r17],16
-	extr.u r19=rCRIPSR,32,2	// extract ps.cpl
 	;;
-	ld8.fill r14=[r16],16
-	ld8.fill r15=[r17],16
-	cmp.eq p6,p7=r0,r19	// are we returning to kernel mode? (psr.cpl==0)
+	ld8.fill r14=[r16]
+	ld8.fill r15=[r17]
+	shr.u r18=r19,16	// get byte size of existing "dirty" partition
 	;;
-	mov b6=rB6
-	mov ar.pfs=rARPFS
-(p6)	br.cond.dpnt.few skip_rbs_switch
-
+	mov r16=ar.bsp		// get existing backing store pointer
+	movl r17=PERCPU_ADDR+IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET
+	;;
+	ld4 r17=[r17]		// r17 = cpu_data->phys_stacked_size_p8
+(pKern)	br.cond.dpnt.few skip_rbs_switch
 	/*
 	 * Restore user backing store.
 	 *
 	 * NOTE: alloc, loadrs, and cover can't be predicated.
-	 *
-	 * XXX This needs some scheduling/tuning once we believe it
-	 *     really does work as intended.
 	 */
-	mov r16=ar.bsp			// get existing backing store pointer
 (pNonSys) br.cond.dpnt.few dont_preserve_current_frame
 	cover				// add current frame into dirty partition
 	;;
-	mov rCRIFS=cr.ifs		// fetch the cr.ifs value that "cover" produced
-	mov r17=ar.bsp			// get new backing store pointer
-	;;
-	sub r16=r17,r16			// calculate number of bytes that were added to rbs
+	mov r19=ar.bsp			// get new backing store pointer
+	sub r16=r16,r18			// krbs = old bsp - size of dirty partition
+	cmp.ne p9,p0=r0,r0		// clear p9 to skip restore of cr.ifs
 	;;
-	shl r16=r16,16			// shift additional frame size into position for loadrs
+	sub r19=r19,r16			// calculate total byte size of dirty partition
+	add r18=64,r18			// don't force in0-in7 into memory...
 	;;
-	add r18=r16,r18			// adjust the loadrs value
+	shl r19=r19,16			// shift size of dirty partition into loadrs position
 	;;
 dont_preserve_current_frame:
-	alloc r16=ar.pfs,0,0,0,0	// drop the current call frame (noop for syscalls)
-	;;
-	mov ar.rsc=r18			// load ar.rsc to be used for "loadrs"
-#ifdef CONFIG_IA32_SUPPORT
-	tbit.nz p6,p0=rCRIPSR,IA64_PSR_IS_BIT
+	/*
+	 * To prevent leaking bits between the kernel and user-space,
+	 * we must clear the stacked registers in the "invalid" partition here.
+	 * Not pretty, but at least it's fast (3.34 registers/cycle).
+	 * Architecturally, this loop could go at 4.67 registers/cycle, but that would
+	 * oversubscribe Itanium.
+	 */
+#	define pRecurse	p6
+#	define pReturn	p7
+#	define Nregs	10
+	alloc loc0=ar.pfs,2,Nregs-2,2,0
+	shr.u loc1=r18,9		// RNaTslots <= dirtySize / (64*8) + 1
+	sub r17=r17,r18			// r17 = (physStackedSize + 8) - dirtySize
+	;;
+	mov ar.rsc=r19			// load ar.rsc to be used for "loadrs"
+	shladd in0=loc1,3,r17
+	mov in1=0
+	;;
+	.align 32
+rse_clear_invalid:
+	// cycle 0
+ { .mii
+	alloc loc0=ar.pfs,2,Nregs-2,2,0
+	cmp.lt pRecurse,p0=Nregs*8,in0	// if more than Nregs regs left to clear, (re)curse
+	add out0=-Nregs*8,in0
+}{ .mfb
+	add out1=1,in1			// increment recursion count
+	nop.f 0
+	nop.b 0				// can't do br.call here because of alloc (WAW on CFM)
+	;;
+}{ .mfi	// cycle 1
+	mov loc1=0
+	nop.f 0
+	mov loc2=0
+}{ .mib
+	mov loc3=0
+	mov loc4=0
+(pRecurse) br.call.sptk.few b6=rse_clear_invalid
+
+}{ .mfi	// cycle 2
+	mov loc5=0
+	nop.f 0
+	cmp.ne pReturn,p0=r0,in1	// if recursion count != 0, we need to do a br.ret
+}{ .mib
+	mov loc6=0
+	mov loc7=0
+(pReturn) br.ret.sptk.few b6
+}
+#	undef pRecurse
+#	undef pReturn
+
+	alloc r17=ar.pfs,0,0,0,0	// drop current register frame
 	;;
-(p6)	mov ar.rsc=r0                   // returning to IA32 mode
-#endif
- 	;;
 	loadrs
 	;;
-	mov ar.bspstore=rARBSPSTORE
-	;;
-	mov ar.rnat=rARRNAT	// must happen with RSE in lazy mode
-
 skip_rbs_switch:
+	mov b6=rB6
+	mov ar.pfs=rARPFS
+(pUser)	mov ar.bspstore=rARBSPSTORE
+(p9)	mov cr.ifs=rCRIFS
+	mov cr.ipsr=rCRIPSR
+	mov cr.iip=rCRIIP
+	;;
+(pUser)	mov ar.rnat=rARRNAT	// must happen with RSE in lazy mode
 	mov ar.rsc=rARRSC
 	mov ar.unat=rARUNAT
-	mov cr.ifs=rCRIFS	// restore cr.ifs only if not a (synchronous) syscall
 	mov pr=rARPR,-1
-	mov cr.iip=rCRIIP
-	mov cr.ipsr=rCRIPSR
-	;;
-	rfi;;			// must be last instruction in an insn group
+	rfi
 END(ia64_leave_kernel)
 
 ENTRY(handle_syscall_error)
@@ -784,13 +792,13 @@
 	br.cond.sptk.many ia64_leave_kernel
 END(handle_syscall_error)
 
-#ifdef CONFIG_SMP
+# ifdef CONFIG_SMP
 	/*
 	 * Invoke schedule_tail(task) while preserving in0-in7, which may be needed
 	 * in case a system call gets restarted.
 	 */
 ENTRY(invoke_schedule_tail)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
 	alloc loc1=ar.pfs,8,2,1,0
 	mov loc0=rp
 	mov out0=r8				// Address of previous task
@@ -801,35 +809,24 @@
 	br.ret.sptk.many rp
 END(invoke_schedule_tail)
 
-#endif /* CONFIG_SMP */
-
-#ifdef CONFIG_IA64_SOFTSDV_HACKS
-
-ENTRY(invoke_ia64_reset_itm)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8))
-	alloc loc1=ar.pfs,8,2,0,0
-	mov loc0=rp
-	;;
-	UNW(.body)
-	br.call.sptk.many rp=ia64_reset_itm
-.ret12:	;;
-	mov ar.pfs=loc1
-	mov rp=loc0
-	br.ret.sptk.many rp
-END(invoke_ia64_reset_itm)
-
-#endif /* CONFIG_IA64_SOFTSDV_HACKS */
+# endif /* CONFIG_SMP */
 
+#if __GNUC__ < 3
 	/*
 	 * Invoke do_softirq() while preserving in0-in7, which may be needed
-	 * in case a system call gets restarted.
+	 * in case a system call gets restarted.  Note that declaring do_softirq()
+	 * with asmlinkage() is NOT enough because that will only preserve as many
+	 * registers as there are formal arguments.
+	 *
+	 * XXX fix me: with gcc 3.0, we won't need this anymore because syscall_linkage
+	 *	renders all eight input registers (in0-in7) as "untouchable".
 	 */
 ENTRY(invoke_do_softirq)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
 	alloc loc1=ar.pfs,8,2,0,0
 	mov loc0=rp
 	;;
-	UNW(.body)
+	.body
 	br.call.sptk.few rp=do_softirq
 .ret13:	mov ar.pfs=loc1
 	mov rp=loc0
@@ -838,27 +835,33 @@
 
 	/*
 	 * Invoke schedule() while preserving in0-in7, which may be needed
-	 * in case a system call gets restarted.
+	 * in case a system call gets restarted.  Note that declaring schedule()
+	 * with asmlinkage() is NOT enough because that will only preserve as many
+	 * registers as there are formal arguments.
+	 *
+	 * XXX fix me: with gcc 3.0, we won't need this anymore because syscall_linkage
+	 *	renders all eight input registers (in0-in7) as "untouchable".
 	 */
 ENTRY(invoke_schedule)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
 	alloc loc1=ar.pfs,8,2,0,0
 	mov loc0=rp
 	;;
-	UNW(.body)
+	.body
 	br.call.sptk.few rp=schedule
 .ret14:	mov ar.pfs=loc1
 	mov rp=loc0
 	br.ret.sptk.many rp
 END(invoke_schedule)
 
-	//
-	// Setup stack and call ia64_do_signal.  Note that pSys and pNonSys need to
-	// be set up by the caller.  We declare 8 input registers so the system call
-	// args get preserved, in case we need to restart a system call.
-	//
+#endif /* __GNUC__ < 3 */
+
+	/*
+	 * Setup stack and call ia64_do_signal.  Note that pSys and pNonSys need to
+	 * be set up by the caller.  We declare 8 input registers so the system call
+	 * args get preserved, in case we need to restart a system call.
+	 */
 ENTRY(handle_signal_delivery)
-#ifdef CONFIG_IA64_NEW_UNWIND
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
 	alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
 	mov r9=ar.unat
@@ -882,26 +885,9 @@
 	mov ar.unat=r9
 	mov ar.pfs=loc1
 	br.ret.sptk.many rp
-#else /* !CONFIG_IA64_NEW_UNWIND */
-	.prologue
-	alloc r16=ar.pfs,8,0,3,0 // preserve all eight input regs in case of syscall restart!
-	DO_SAVE_SWITCH_STACK
-	UNW(.body)
-
-	mov out0=0				// there is no "oldset"
-	adds out1=16,sp				// out1=&sigscratch
-	.pred.rel.mutex pSys, pNonSys
-(pSys)	mov out2=1				// out2==1 => we're in a syscall
-(pNonSys) mov out2=0				// out2==0 => not a syscall
-	br.call.sptk.few rp=ia64_do_signal
-.ret16:	// restore the switch stack (ptrace may have modified it)
-	DO_LOAD_SWITCH_STACK( )
-	br.ret.sptk.many rp
-#endif /* !CONFIG_IA64_NEW_UNWIND */
 END(handle_signal_delivery)
 
 GLOBAL_ENTRY(sys_rt_sigsuspend)
-#ifdef CONFIG_IA64_NEW_UNWIND
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
 	alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
 	mov r9=ar.unat
@@ -924,87 +910,43 @@
 	mov ar.unat=r9
 	mov ar.pfs=loc1
 	br.ret.sptk.many rp
-#else /* !CONFIG_IA64_NEW_UNWIND */
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2))
-	alloc r16=ar.pfs,2,0,3,0
-	DO_SAVE_SWITCH_STACK
-	UNW(.body)
-
-	mov out0=in0				// mask
-	mov out1=in1				// sigsetsize
-	adds out2=16,sp				// out1=&sigscratch
-	br.call.sptk.many rp=ia64_rt_sigsuspend
-.ret18:	// restore the switch stack (ptrace may have modified it)
-	DO_LOAD_SWITCH_STACK( )
-	br.ret.sptk.many rp
-#endif /* !CONFIG_IA64_NEW_UNWIND */
 END(sys_rt_sigsuspend)
 
 ENTRY(sys_rt_sigreturn)
-#ifdef CONFIG_IA64_NEW_UNWIND
-	.regstk 0,0,3,0	// inherited from gate.s:invoke_sighandler()
 	PT_REGS_UNWIND_INFO(0)
+	alloc r2=ar.pfs,0,0,1,0
 	.prologue
 	PT_REGS_SAVES(16)
 	adds sp=-16,sp
 	.body
-	cmp.eq pNonSys,p0=r0,r0			// sigreturn isn't a normal syscall...
+	cmp.eq pNonSys,pSys=r0,r0		// sigreturn isn't a normal syscall...
 	;;
 	adds out0=16,sp				// out0 = &sigscratch
 	br.call.sptk.few rp=ia64_rt_sigreturn
-.ret19:	adds sp=16,sp		// doesn't drop pt_regs, so don't mark it as restoring sp!
-	PT_REGS_UNWIND_INFO(0)	// instead, create a new body section with the smaller frame
+.ret19:	.restore sp 0
+	adds sp=16,sp
 	;;
 	ld8 r9=[sp]				// load new ar.unat
-	mov b7=r8
+	MOVBR(.sptk,b7,r8,ia64_leave_kernel)
 	;;
 	mov ar.unat=r9
 	br b7
-#else /* !CONFIG_IA64_NEW_UNWIND */
-	.regstk 0,0,3,0	// inherited from gate.s:invoke_sighandler()
-	PT_REGS_UNWIND_INFO(0)
-	UNW(.prologue)
-	UNW(.fframe IA64_PT_REGS_SIZE+IA64_SWITCH_STACK_SIZE)
-	UNW(.spillsp rp, PT(CR_IIP)+IA64_SWITCH_STACK_SIZE)
-	UNW(.spillsp ar.pfs, PT(CR_IFS)+IA64_SWITCH_STACK_SIZE)
-	UNW(.spillsp ar.unat, PT(AR_UNAT)+IA64_SWITCH_STACK_SIZE)
-	UNW(.spillsp pr, PT(PR)+IA64_SWITCH_STACK_SIZE)
-	adds sp=-IA64_SWITCH_STACK_SIZE,sp
-	cmp.eq pNonSys,p0=r0,r0			// sigreturn isn't a normal syscall...
-	;;
-	UNW(.body)
-
-	adds out0=16,sp				// out0 = &sigscratch
-	br.call.sptk.few rp=ia64_rt_sigreturn
-.ret20:	adds r3=IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp
-	;;
-	ld8 r9=[r3]			// load new ar.unat
-	mov b7=r8
-	;;
-	PT_REGS_UNWIND_INFO(0)
-	adds sp=IA64_SWITCH_STACK_SIZE,sp	// drop (dummy) switch-stack frame
-	mov ar.unat=r9
-	br b7
-#endif /* !CONFIG_IA64_NEW_UNWIND */
 END(sys_rt_sigreturn)
 
 GLOBAL_ENTRY(ia64_prepare_handle_unaligned)
 	//
-	// r16 = fake ar.pfs, we simply need to make sure 
+	// r16 = fake ar.pfs, we simply need to make sure
 	// privilege is still 0
 	//
-	PT_REGS_UNWIND_INFO(0)
-	mov r16=r0 				
-	UNW(.prologue)
+	mov r16=r0
+	.prologue
 	DO_SAVE_SWITCH_STACK
 	br.call.sptk.few rp=ia64_handle_unaligned // stack frame setup in ivt
 .ret21:	.body
-	DO_LOAD_SWITCH_STACK(PT_REGS_UNWIND_INFO(0))
+	DO_LOAD_SWITCH_STACK
 	br.cond.sptk.many rp			  // goes to ia64_leave_kernel
 END(ia64_prepare_handle_unaligned)
 
-#ifdef CONFIG_IA64_NEW_UNWIND
-
 	//
 	// unw_init_running(void (*callback)(info, arg), void *arg)
 	//
@@ -1050,8 +992,6 @@
 	br.ret.sptk.many rp
 END(unw_init_running)
 
-#endif
-
 	.rodata
 	.align 8
 	.globl sys_call_table
@@ -1229,7 +1169,7 @@
 	data8 sys_accept
 	data8 sys_getsockname			// 1195
 	data8 sys_getpeername
-	data8 sys_socketpair 
+	data8 sys_socketpair
 	data8 sys_send
 	data8 sys_sendto
 	data8 sys_recv				// 1200
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/entry.h linux/arch/ia64/kernel/entry.h
--- v2.4.3/linux/arch/ia64/kernel/entry.h	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/kernel/entry.h	Thu Apr  5 12:51:47 2001
@@ -1,65 +1,77 @@
+#include <linux/config.h>
+
+/* XXX fixme */
+#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC)
+# define MOVBR(type,br,gr,lbl)	mov br=gr
+#else
+# define MOVBR(type,br,gr,lbl)	mov##type br=gr,lbl
+#endif
+
 /*
  * Preserved registers that are shared between code in ivt.S and entry.S.  Be
  * careful not to step on these!
  */
 #define pKern		p2	/* will leave_kernel return to kernel-mode? */
+#define pUser		p3	/* will leave_kernel return to user-mode? */
 #define pSys		p4	/* are we processing a (synchronous) system call? */
 #define pNonSys		p5	/* complement of pSys */
 
-#define PT(f)		(IA64_PT_REGS_##f##_OFFSET + 16)
-#define SW(f)		(IA64_SWITCH_STACK_##f##_OFFSET + 16)
+#define PT(f)		(IA64_PT_REGS_##f##_OFFSET)
+#define SW(f)		(IA64_SWITCH_STACK_##f##_OFFSET)
 
-#define PT_REGS_SAVES(off)				\
-	UNW(.unwabi @svr4, 'i');			\
-	UNW(.fframe IA64_PT_REGS_SIZE+16+(off));	\
-	UNW(.spillsp rp, PT(CR_IIP)+(off));		\
-	UNW(.spillsp ar.pfs, PT(CR_IFS)+(off));		\
-	UNW(.spillsp ar.unat, PT(AR_UNAT)+(off));	\
-	UNW(.spillsp ar.fpsr, PT(AR_FPSR)+(off));	\
-	UNW(.spillsp pr, PT(PR)+(off));
+#define PT_REGS_SAVES(off)			\
+	.unwabi @svr4, 'i';			\
+	.fframe IA64_PT_REGS_SIZE+16+(off);	\
+	.spillsp rp, PT(CR_IIP)+16+(off);	\
+	.spillsp ar.pfs, PT(CR_IFS)+16+(off);	\
+	.spillsp ar.unat, PT(AR_UNAT)+16+(off);	\
+	.spillsp ar.fpsr, PT(AR_FPSR)+16+(off);	\
+	.spillsp pr, PT(PR)+16+(off);
 
 #define PT_REGS_UNWIND_INFO(off)		\
-	UNW(.prologue);				\
+	.prologue;				\
 	PT_REGS_SAVES(off);			\
-	UNW(.body)
+	.body
 
-#define SWITCH_STACK_SAVES(off)									  \
-	UNW(.savesp ar.unat,SW(CALLER_UNAT)+(off)); UNW(.savesp ar.fpsr,SW(AR_FPSR)+(off));	  \
-	UNW(.spillsp f2,SW(F2)+(off)); UNW(.spillsp f3,SW(F3)+(off));				  \
-	UNW(.spillsp f4,SW(F4)+(off)); UNW(.spillsp f5,SW(F5)+(off));				  \
-	UNW(.spillsp f16,SW(F16)+(off)); UNW(.spillsp f17,SW(F17)+(off));			  \
-	UNW(.spillsp f18,SW(F18)+(off)); UNW(.spillsp f19,SW(F19)+(off));			  \
-	UNW(.spillsp f20,SW(F20)+(off)); UNW(.spillsp f21,SW(F21)+(off));			  \
-	UNW(.spillsp f22,SW(F22)+(off)); UNW(.spillsp f23,SW(F23)+(off));			  \
-	UNW(.spillsp f24,SW(F24)+(off)); UNW(.spillsp f25,SW(F25)+(off));			  \
-	UNW(.spillsp f26,SW(F26)+(off)); UNW(.spillsp f27,SW(F27)+(off));			  \
-	UNW(.spillsp f28,SW(F28)+(off)); UNW(.spillsp f29,SW(F29)+(off));			  \
-	UNW(.spillsp f30,SW(F30)+(off)); UNW(.spillsp f31,SW(F31)+(off));			  \
-	UNW(.spillsp r4,SW(R4)+(off)); UNW(.spillsp r5,SW(R5)+(off));				  \
-	UNW(.spillsp r6,SW(R6)+(off)); UNW(.spillsp r7,SW(R7)+(off));				  \
-	UNW(.spillsp b0,SW(B0)+(off)); UNW(.spillsp b1,SW(B1)+(off));				  \
-	UNW(.spillsp b2,SW(B2)+(off)); UNW(.spillsp b3,SW(B3)+(off));				  \
-	UNW(.spillsp b4,SW(B4)+(off)); UNW(.spillsp b5,SW(B5)+(off));				  \
-	UNW(.spillsp ar.pfs,SW(AR_PFS)+(off)); UNW(.spillsp ar.lc,SW(AR_LC)+(off));		  \
-	UNW(.spillsp @priunat,SW(AR_UNAT)+(off));						  \
-	UNW(.spillsp ar.rnat,SW(AR_RNAT)+(off)); UNW(.spillsp ar.bspstore,SW(AR_BSPSTORE)+(off)); \
-	UNW(.spillsp pr,SW(PR)+(off))
+#define SWITCH_STACK_SAVES(off)							\
+	.savesp ar.unat,SW(CALLER_UNAT)+16+(off);				\
+	.savesp ar.fpsr,SW(AR_FPSR)+16+(off);					\
+	.spillsp f2,SW(F2)+16+(off); .spillsp f3,SW(F3)+16+(off);		\
+	.spillsp f4,SW(F4)+16+(off); .spillsp f5,SW(F5)+16+(off);		\
+	.spillsp f16,SW(F16)+16+(off); .spillsp f17,SW(F17)+16+(off);		\
+	.spillsp f18,SW(F18)+16+(off); .spillsp f19,SW(F19)+16+(off);		\
+	.spillsp f20,SW(F20)+16+(off); .spillsp f21,SW(F21)+16+(off);		\
+	.spillsp f22,SW(F22)+16+(off); .spillsp f23,SW(F23)+16+(off);		\
+	.spillsp f24,SW(F24)+16+(off); .spillsp f25,SW(F25)+16+(off);		\
+	.spillsp f26,SW(F26)+16+(off); .spillsp f27,SW(F27)+16+(off);		\
+	.spillsp f28,SW(F28)+16+(off); .spillsp f29,SW(F29)+16+(off);		\
+	.spillsp f30,SW(F30)+16+(off); .spillsp f31,SW(F31)+16+(off);		\
+	.spillsp r4,SW(R4)+16+(off); .spillsp r5,SW(R5)+16+(off);		\
+	.spillsp r6,SW(R6)+16+(off); .spillsp r7,SW(R7)+16+(off);		\
+	.spillsp b0,SW(B0)+16+(off); .spillsp b1,SW(B1)+16+(off);		\
+	.spillsp b2,SW(B2)+16+(off); .spillsp b3,SW(B3)+16+(off);		\
+	.spillsp b4,SW(B4)+16+(off); .spillsp b5,SW(B5)+16+(off);		\
+	.spillsp ar.pfs,SW(AR_PFS)+16+(off); .spillsp ar.lc,SW(AR_LC)+16+(off);	\
+	.spillsp @priunat,SW(AR_UNAT)+16+(off);					\
+	.spillsp ar.rnat,SW(AR_RNAT)+16+(off);					\
+	.spillsp ar.bspstore,SW(AR_BSPSTORE)+16+(off);				\
+	.spillsp pr,SW(PR)+16+(off))
 
 #define DO_SAVE_SWITCH_STACK			\
 	movl r28=1f;				\
 	;;					\
 	.fframe IA64_SWITCH_STACK_SIZE;		\
 	adds sp=-IA64_SWITCH_STACK_SIZE,sp;	\
-	mov b7=r28;				\
+	MOVBR(.ret.sptk,b7,r28,1f);		\
 	SWITCH_STACK_SAVES(0);			\
 	br.cond.sptk.many save_switch_stack;	\
 1:
 
-#define DO_LOAD_SWITCH_STACK(extra)		\
+#define DO_LOAD_SWITCH_STACK			\
 	movl r28=1f;				\
 	;;					\
-	mov b7=r28;				\
+	invala;					\
+	MOVBR(.ret.sptk,b7,r28,1f);		\
 	br.cond.sptk.many load_switch_stack;	\
-1:	UNW(.restore sp);			\
-	extra;					\
+1:	.restore sp;				\
 	adds sp=IA64_SWITCH_STACK_SIZE,sp
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/fw-emu.c linux/arch/ia64/kernel/fw-emu.c
--- v2.4.3/linux/arch/ia64/kernel/fw-emu.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/fw-emu.c	Thu Apr  5 12:51:47 2001
@@ -1,8 +1,8 @@
 /*
  * PAL & SAL emulation.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * For the HP simulator, this file gets include in boot/bootloader.c.
  * For SoftSDV, this file gets included in sys_softsdv.c.
@@ -22,7 +22,8 @@
 
 #define NUM_MEM_DESCS	2
 
-static char fw_mem[(  sizeof(efi_system_table_t)
+static char fw_mem[(  sizeof(struct ia64_boot_param)
+		    + sizeof(efi_system_table_t)
 		    + sizeof(efi_runtime_services_t)
 		    + 1*sizeof(efi_config_table_t)
 		    + sizeof(struct ia64_sal_systab)
@@ -151,6 +152,14 @@
 	movl r10=0x100000100		/* bus_ratio<<32 (1/256) */
 	movl r11=0x100000064		/* itc_ratio<<32 (1/100) */
 	;;
+1:	cmp.eq p6,p7=19,r28		/* PAL_RSE_INFO */
+(p7)	br.cond.sptk.few 1f
+	mov r8=0			/* status = 0 */
+	mov r9=96			/* num phys stacked */
+	mov r10=0			/* hints */
+	mov r11=0
+	br.cond.sptk.few rp
+
 1:	cmp.eq p6,p7=1,r28		/* PAL_CACHE_FLUSH */
 (p7)	br.cond.sptk.few 1f
 	mov r9=ar.lc
@@ -168,8 +177,7 @@
 	;;
 	mov ar.lc=r9
 	mov r8=r0
-1:
-	br.cond.sptk.few rp
+1:	br.cond.sptk.few rp
 
 stacked:
 	br.ret.sptk.few rp
@@ -249,13 +257,7 @@
 			 * or something platform specific?  The SAL
 			 * doc ain't exactly clear on this...
 			 */
-#if defined(CONFIG_IA64_SOFTSDV_HACKS)
-			r9 =   4000000;
-#elif defined(CONFIG_IA64_SDV)
-			r9 = 300000000;
-#else
 			r9 = 700000000;
-#endif
 			break;
 
 		      case SAL_FREQ_BASE_REALTIME_CLOCK:
@@ -332,7 +334,7 @@
 	return (void *) addr;
 }
 
-void
+struct ia64_boot_param *
 sys_fw_init (const char *args, int arglen)
 {
 	efi_system_table_t *efi_systab;
@@ -358,6 +360,7 @@
 	sal_systab  = (void *) cp; cp += sizeof(*sal_systab);
 	sal_ed      = (void *) cp; cp += sizeof(*sal_ed);
 	efi_memmap  = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap);
+	bp	    = (void *) cp; cp += sizeof(*bp);
 	cmd_line    = (void *) cp;
 
 	if (args) {
@@ -423,7 +426,7 @@
 	strcpy(sal_systab->product_id, "SN1");
 #endif
 
-	/* fill in an entry point: */	
+	/* fill in an entry point: */
 	sal_ed->type = SAL_DESC_ENTRY_POINT;
 	sal_ed->pal_proc = __pa(pal_desc[0]);
 	sal_ed->sal_proc = __pa(sal_desc[0]);
@@ -440,15 +443,15 @@
 	md->pad = 0;
 	md->phys_addr = 2*MB;
 	md->virt_addr = 0;
-	md->num_pages = (64*MB) >> 12;	/* 64MB (in 4KB pages) */
+	md->num_pages = (128*MB) >> 12;	/* 128MB (in 4KB pages) */
 	md->attribute = EFI_MEMORY_WB;
 
 	/* descriptor for firmware emulator: */
 	md = &efi_memmap[1];
-	md->type = EFI_RUNTIME_SERVICES_DATA;
+	md->type = EFI_PAL_CODE;
 	md->pad = 0;
 	md->phys_addr = 1*MB;
-	md->virt_addr = 0;
+	md->virt_addr = 1*MB;
 	md->num_pages = (1*MB) >> 12;	/* 1MB (in 4KB pages) */
 	md->attribute = EFI_MEMORY_WB;
 
@@ -468,7 +471,6 @@
 	md->attribute = EFI_MEMORY_WB;
 #endif
 
-	bp = id(ZERO_PAGE_ADDR);
 	bp->efi_systab = __pa(&fw_mem);
 	bp->efi_memmap = __pa(efi_memmap);
 	bp->efi_memmap_size = NUM_MEM_DESCS*sizeof(efi_memory_desc_t);
@@ -479,6 +481,7 @@
 	bp->console_info.num_rows = 25;
 	bp->console_info.orig_x = 0;
 	bp->console_info.orig_y = 24;
-	bp->num_pci_vectors = 0;
 	bp->fpswa = 0;
+
+	return bp;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/gate.S linux/arch/ia64/kernel/gate.S
--- v2.4.3/linux/arch/ia64/kernel/gate.S	Fri Jul 14 16:08:11 2000
+++ linux/arch/ia64/kernel/gate.S	Thu Apr  5 12:51:47 2001
@@ -1,10 +1,9 @@
 /*
- * This file contains the code that gets mapped at the upper end of
- * each task's text region.  For now, it contains the signal
- * trampoline code only.
+ * This file contains the code that gets mapped at the upper end of each task's text
+ * region.  For now, it contains the signal trampoline code only.
  *
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #include <asm/asmmacro.h>
@@ -14,11 +13,7 @@
 #include <asm/unistd.h>
 #include <asm/page.h>
 
-	.psr abi64
-	.psr lsb
-	.lsb
-
-	.section __gate_section,"ax"
+	.section .text.gate,"ax"
 
 	.align PAGE_SIZE
 
@@ -51,28 +46,24 @@
 	 *   |            space              |
 	 *   +-------------------------------+ <-- sp
 	 *
-	 * The register stack looks _exactly_ the way it looked at the
-	 * time the signal occurred.  In other words, we're treading
-	 * on a potential mine-field: each incoming general register
-	 * may be a NaT value (includeing sp, in which case the process
-	 * ends up dying with a SIGSEGV).
+	 * The register stack looks _exactly_ the way it looked at the time the signal
+	 * occurred.  In other words, we're treading on a potential mine-field: each
+	 * incoming general register may be a NaT value (including sp, in which case the
+	 * process ends up dying with a SIGSEGV).
 	 *
-	 * The first need to do is a cover to get the registers onto
-	 * the backing store.  Once that is done, we invoke the signal
-	 * handler which may modify some of the machine state.  After
-	 * returning from the signal handler, we return control to the
-	 * previous context by executing a sigreturn system call.  A
-	 * signal handler may call the rt_sigreturn() function to
-	 * directly return to a given sigcontext.  However, the
-	 * user-level sigreturn() needs to do much more than calling
-	 * the rt_sigreturn() system call as it needs to unwind the
-	 * stack to restore preserved registers that may have been
-	 * saved on the signal handler's call stack.
+	 * The first need to do is a cover to get the registers onto the backing store.
+	 * Once that is done, we invoke the signal handler which may modify some of the
+	 * machine state.  After returning from the signal handler, we return control to
+	 * the previous context by executing a sigreturn system call.  A signal handler
+	 * may call the rt_sigreturn() function to directly return to a given sigcontext.
+	 * However, the user-level sigreturn() needs to do much more than calling the
+	 * rt_sigreturn() system call as it needs to unwind the stack to restore preserved
+	 * registers that may have been saved on the signal handler's call stack.
 	 *
 	 * On entry:
 	 *	r2	= signal number
 	 *	r3	= plabel of signal handler
-	 *	r15	= new register backing store (ignored)
+	 *	r15	= new register backing store
 	 *	[sp+16] = sigframe
 	 */
 
@@ -153,7 +144,7 @@
 
 ENTRY(setup_rbs)
 	flushrs					// must be first in insn
-	mov ar.rsc=r0				// put RSE into enforced lazy mode
+	mov ar.rsc=0				// put RSE into enforced lazy mode
 	adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
 	;;
 	mov r14=ar.rnat				// get rnat as updated by flushrs
@@ -167,7 +158,7 @@
 
 ENTRY(restore_rbs)
 	flushrs
-	mov ar.rsc=r0				// put RSE into enforced lazy mode
+	mov ar.rsc=0				// put RSE into enforced lazy mode
 	adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
 	;;
 	ld8 r14=[r16]				// get new rnat
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/head.S linux/arch/ia64/kernel/head.S
--- v2.4.3/linux/arch/ia64/kernel/head.S	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/head.S	Thu Apr  5 12:51:47 2001
@@ -5,8 +5,9 @@
  * to set up the kernel's global pointer and jump to the kernel
  * entry point.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2001 Stephane Eranian <eranian@hpl.hp.com>
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  * Copyright (C) 1999 Intel Corp.
@@ -18,16 +19,15 @@
 
 #include <asm/asmmacro.h>
 #include <asm/fpu.h>
-#include <asm/pal.h>
+#include <asm/kregs.h>
+#include <asm/mmu_context.h>
 #include <asm/offsets.h>
+#include <asm/pal.h>
+#include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 
-	.psr abi64
-	.psr lsb
-	.lsb
-
 	.section __special_page_section,"ax"
 
 	.global empty_zero_page
@@ -38,29 +38,66 @@
 swapper_pg_dir:
 	.skip PAGE_SIZE
 
-	.global empty_bad_page
-empty_bad_page:
-	.skip PAGE_SIZE
-
-	.global empty_bad_pte_table
-empty_bad_pte_table:
-	.skip PAGE_SIZE
-
-	.global empty_bad_pmd_table
-empty_bad_pmd_table:
-	.skip PAGE_SIZE
-
 	.rodata
 halt_msg:
 	stringz "Halting kernel\n"
 
 	.text
 
+	.global start_ap
+
+	/*
+	 * Start the kernel.  When the bootloader passes control to _start(), r28
+	 * points to the address of the boot parameter area.  Execution reaches
+	 * here in physical mode.
+	 */
 GLOBAL_ENTRY(_start)
-	UNW(.prologue)
-	UNW(.save rp, r4)		// terminate unwind chain with a NULL rp
-	UNW(mov r4=r0)
-	UNW(.body)
+start_ap:
+	.prologue
+	.save rp, r4		// terminate unwind chain with a NULL rp
+	mov r4=r0
+	.body
+
+	/*
+	 * Initialize the region register for region 7 and install a translation register
+	 * that maps the kernel's text and data:
+	 */
+	rsm psr.i | psr.ic
+	mov r16=((ia64_rid(IA64_REGION_ID_KERNEL, PAGE_OFFSET) << 8) | (_PAGE_SIZE_64M << 2))
+	;;
+	srlz.i
+	mov r18=_PAGE_SIZE_64M<<2
+	movl r17=PAGE_OFFSET + 64*1024*1024
+	;;
+	mov rr[r17]=r16
+	mov cr.itir=r18
+	mov cr.ifa=r17
+	mov r16=IA64_TR_KERNEL
+	movl r18=(64*1024*1024 | PAGE_KERNEL)
+	;;
+	srlz.i
+	;;
+	itr.i itr[r16]=r18
+	;;
+	itr.d dtr[r16]=r18
+	;;
+	srlz.i
+
+	/*
+	 * Switch into virtual mode:
+	 */
+	movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN)
+	;;
+	mov cr.ipsr=r16
+	movl r17=1f
+	;;
+	mov cr.iip=r17
+	mov cr.ifs=r0
+	;;
+	rfi
+	;;
+1:	// now we are in virtual mode
+
 	// set IVT entry point---can't access I/O ports without it
 	movl r3=ia64_ivt
 	;;
@@ -74,7 +111,7 @@
 	;;
 
 #ifdef CONFIG_IA64_EARLY_PRINTK
-	mov r3=(6<<8) | (28<<2)
+	mov r3=(6<<8) | (_PAGE_SIZE_64M<<2)
 	movl r2=6<<61
 	;;
 	mov rr[r2]=r3
@@ -83,27 +120,32 @@
 	;;
 #endif
 
-#define isAP	p2	// are we booting an Application Processor (not the BSP)?
+#define isAP	p2	// are we an Application Processor?
+#define isBP	p3	// are we the Bootstrap Processor?
 
-	// Find the init_task for the currently booting CPU.  At poweron, and in
-	// UP mode, cpu_now_booting is 0
+	/*
+	 * Find the init_task for the currently booting CPU.  At poweron, and in
+	 * UP mode, cpu_now_booting is 0.
+	 */
 	movl r3=cpu_now_booting
  	;;
-	ld4 r3=[r3]
+	ld4 r3=[r3]		// r3 <- smp_processor_id()
 	movl r2=init_tasks
-	;; 
+	;;
 	shladd r2=r3,3,r2
 	;;
 	ld8 r2=[r2]
-	cmp4.ne isAP,p0=r3,r0	// p9 == true if this is an application processor (ap)
+	cmp4.ne isAP,isBP=r3,r0
 	;;			// RAW on r2
 	extr r3=r2,0,61		// r3 == phys addr of task struct
 	;;
 
-	// load the "current" pointer (r13) and ar.k6 with the current task 
+	// load the "current" pointer (r13) and ar.k6 with the current task
 	mov r13=r2
-	mov ar.k6=r3		// Physical address
-	;;
+	mov IA64_KR(CURRENT)=r3		// Physical address
+
+	// initialize k4 to a safe value (64-128MB is mapped by TR_KERNEL)
+	mov IA64_KR(CURRENT_STACK)=1
 	/*
 	 * Reserve space at the top of the stack for "struct pt_regs".  Kernel threads
 	 * don't store interesting values in that structure, but the space still needs
@@ -113,14 +155,18 @@
 	 */
 	addl r12=IA64_STK_OFFSET-IA64_PT_REGS_SIZE-16,r2
 	addl r2=IA64_RBS_OFFSET,r2	// initialize the RSE
-	mov ar.rsc=r0		// place RSE in enforced lazy mode
+	mov ar.rsc=0		// place RSE in enforced lazy mode
 	;;
-	mov ar.bspstore=r2	// establish the new RSE stack
+	loadrs			// clear the dirty partition
 	;;
-	loadrs			// load zero bytes from the register stack
+	mov ar.bspstore=r2	// establish the new RSE stack
 	;;
 	mov ar.rsc=0x3		// place RSE in eager mode
+
+(isBP)	dep r28=-1,r28,61,3	// make address virtual
+(isBP)	movl r2=ia64_boot_param
 	;;
+(isBP)	st8 [r2]=r28		// save the address of the boot param area passed by the bootloader
 
 #ifdef CONFIG_IA64_EARLY_PRINTK
 	.rodata
@@ -135,16 +181,12 @@
 1:	// force new bundle
 #endif /* CONFIG_IA64_EARLY_PRINTK */
 
-	alloc r2=ar.pfs,8,0,2,0
-	;;
 #ifdef CONFIG_SMP
 (isAP)	br.call.sptk.few rp=smp_callin
 .ret0:
 (isAP)	br.cond.sptk.few self
 #endif
 
-#undef isAP
-
 	// This is executed by the bootstrap processor (bsp) only:
 
 #ifdef CONFIG_IA64_FW_EMU
@@ -153,9 +195,11 @@
 .ret1:
 #endif
 	br.call.sptk.few rp=start_kernel
-.ret2:	addl r2=@ltoff(halt_msg),gp
+.ret2:	addl r3=@ltoff(halt_msg),gp
+	;;
+	alloc r2=ar.pfs,8,0,2,0
 	;;
-	ld8 out0=[r2]
+	ld8 out0=[r3]
 	br.call.sptk.few b0=console_print
 self:	br.sptk.few self		// endless loop
 END(_start)
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/ia64_ksyms.c linux/arch/ia64/kernel/ia64_ksyms.c
--- v2.4.3/linux/arch/ia64/kernel/ia64_ksyms.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/ia64_ksyms.c	Thu Apr  5 12:51:47 2001
@@ -24,8 +24,11 @@
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strtok);
 
-#include <asm/hw_irq.h>
+#include <linux/irq.h>
 EXPORT_SYMBOL(isa_irq_to_vector_map);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(disable_irq_nosync);
 
 #include <linux/in6.h>
 #include <asm/checksum.h>
@@ -40,10 +43,14 @@
 EXPORT_SYMBOL(__ia64_memcpy_toio);
 EXPORT_SYMBOL(__ia64_memset_c_io);
 
-#include <asm/irq.h>
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(disable_irq_nosync);
+#include <asm/semaphore.h>
+EXPORT_SYMBOL_NOVERS(__down);
+EXPORT_SYMBOL_NOVERS(__down_interruptible);
+EXPORT_SYMBOL_NOVERS(__down_trylock);
+EXPORT_SYMBOL_NOVERS(__up);
+EXPORT_SYMBOL_NOVERS(__down_read_failed);
+EXPORT_SYMBOL_NOVERS(__down_write_failed);
+EXPORT_SYMBOL_NOVERS(__rwsem_wake);
 
 #include <asm/page.h>
 EXPORT_SYMBOL(clear_page);
@@ -57,14 +64,20 @@
 EXPORT_SYMBOL(last_cli_ip);
 #endif
 
+#include <asm/pgalloc.h>
+
 #ifdef CONFIG_SMP
 
+EXPORT_SYMBOL(smp_flush_tlb_all);
+
 #include <asm/current.h>
 #include <asm/hardirq.h>
 EXPORT_SYMBOL(synchronize_irq);
 
 #include <asm/smp.h>
 EXPORT_SYMBOL(smp_call_function);
+EXPORT_SYMBOL(smp_call_function_single);
+EXPORT_SYMBOL(cpu_online_map);
 
 #include <linux/smp.h>
 EXPORT_SYMBOL(smp_num_cpus);
@@ -78,7 +91,11 @@
 EXPORT_SYMBOL(__global_save_flags);
 EXPORT_SYMBOL(__global_restore_flags);
 
-#endif
+#else /* !CONFIG_SMP */
+
+EXPORT_SYMBOL(__flush_tlb_all);
+
+#endif /* !CONFIG_SMP */
 
 #include <asm/uaccess.h>
 EXPORT_SYMBOL(__copy_user);
@@ -111,3 +128,12 @@
 
 extern unsigned long ia64_iobase;
 EXPORT_SYMBOL(ia64_iobase);
+
+#include <asm/pal.h>
+EXPORT_SYMBOL(ia64_pal_call_phys_stacked);
+EXPORT_SYMBOL(ia64_pal_call_phys_static);
+EXPORT_SYMBOL(ia64_pal_call_stacked);
+EXPORT_SYMBOL(ia64_pal_call_static);
+
+extern struct efi efi;
+EXPORT_SYMBOL(efi);
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/iosapic.c linux/arch/ia64/kernel/iosapic.c
--- v2.4.3/linux/arch/ia64/kernel/iosapic.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/iosapic.c	Thu Apr  5 12:51:47 2001
@@ -11,7 +11,7 @@
  * 00/04/19	D. Mosberger	Rewritten to mirror more closely the x86 I/O APIC code.
  *				In particular, we now have separate handlers for edge
  *				and level triggered interrupts.
- * 00/10/27	Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector allocation 
+ * 00/10/27	Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector allocation
  *				PCI to vector mapping, shared PCI interrupts.
  * 00/10/27	D. Mosberger	Document things a bit more to make them more understandable.
  *				Clean up much of the old IOSAPIC cruft.
@@ -79,27 +79,27 @@
 static struct iosapic_irq {
 	char *addr;			/* base address of IOSAPIC */
 	unsigned char base_irq;		/* first irq assigned to this IOSAPIC */
-        char pin;			/* IOSAPIC pin (-1 => not an IOSAPIC irq) */
-	unsigned char dmode 	: 3;	/* delivery mode (see iosapic.h) */
+	char pin;			/* IOSAPIC pin (-1 => not an IOSAPIC irq) */
+	unsigned char dmode	: 3;	/* delivery mode (see iosapic.h) */
 	unsigned char polarity	: 1;	/* interrupt polarity (see iosapic.h) */
 	unsigned char trigger	: 1;	/* trigger mode (see iosapic.h) */
-} iosapic_irq[NR_IRQS];
+} iosapic_irq[IA64_NUM_VECTORS];
 
 /*
  * Translate IOSAPIC irq number to the corresponding IA-64 interrupt vector.  If no
  * entry exists, return -1.
  */
-static int 
+static int
 iosapic_irq_to_vector (int irq)
 {
 	int vector;
 
-	for (vector = 0; vector < NR_IRQS; ++vector)
+	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
 		if (iosapic_irq[vector].base_irq + iosapic_irq[vector].pin == irq)
 			return vector;
 	return -1;
 }
-		
+
 /*
  * Map PCI pin to the corresponding IA-64 interrupt vector.  If no such mapping exists,
  * return -1.
@@ -137,14 +137,8 @@
 		 (dmode << IOSAPIC_DELIVERY_SHIFT) |
 		 vector);
 
-#ifdef CONFIG_IA64_AZUSA_HACKS
-	/* set Flush Disable bit */
-	if (addr != (char *) 0xc0000000fec00000)
-		low32 |= (1 << 17);
-#endif
-
 	/* dest contains both id and eid */
-	high32 = (dest << IOSAPIC_DEST_SHIFT);	
+	high32 = (dest << IOSAPIC_DEST_SHIFT);
 
 	writel(IOSAPIC_RTE_HIGH(pin), addr + IOSAPIC_REG_SELECT);
 	writel(high32, addr + IOSAPIC_WINDOW);
@@ -158,16 +152,17 @@
 	/* do nothing... */
 }
 
-static void 
-mask_irq (unsigned int vector)
+static void
+mask_irq (unsigned int irq)
 {
 	unsigned long flags;
 	char *addr;
 	u32 low32;
 	int pin;
+	ia64_vector vec = irq_to_vector(irq);
 
-	addr = iosapic_irq[vector].addr;
-	pin = iosapic_irq[vector].pin;
+	addr = iosapic_irq[vec].addr;
+	pin = iosapic_irq[vec].pin;
 
 	if (pin < 0)
 		return;			/* not an IOSAPIC interrupt! */
@@ -183,16 +178,17 @@
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 }
 
-static void 
-unmask_irq (unsigned int vector)
+static void
+unmask_irq (unsigned int irq)
 {
 	unsigned long flags;
 	char *addr;
 	u32 low32;
 	int pin;
+	ia64_vector vec = irq_to_vector(irq);
 
-	addr = iosapic_irq[vector].addr;
-	pin = iosapic_irq[vector].pin;
+	addr = iosapic_irq[vec].addr;
+	pin = iosapic_irq[vec].pin;
 	if (pin < 0)
 		return;			/* not an IOSAPIC interrupt! */
 
@@ -209,7 +205,7 @@
 
 
 static void
-iosapic_set_affinity (unsigned int vector, unsigned long mask)
+iosapic_set_affinity (unsigned int irq, unsigned long mask)
 {
 	printk("iosapic_set_affinity: not implemented yet\n");
 }
@@ -219,16 +215,18 @@
  */
 
 static unsigned int
-iosapic_startup_level_irq (unsigned int vector)
+iosapic_startup_level_irq (unsigned int irq)
 {
-	unmask_irq(vector);
+	unmask_irq(irq);
 	return 0;
 }
 
 static void
-iosapic_end_level_irq (unsigned int vector)
+iosapic_end_level_irq (unsigned int irq)
 {
-	writel(vector, iosapic_irq[vector].addr + IOSAPIC_EOI);
+	ia64_vector vec = irq_to_vector(irq);
+
+	writel(vec, iosapic_irq[vec].addr + IOSAPIC_EOI);
 }
 
 #define iosapic_shutdown_level_irq	mask_irq
@@ -252,9 +250,9 @@
  */
 
 static unsigned int
-iosapic_startup_edge_irq (unsigned int vector)
+iosapic_startup_edge_irq (unsigned int irq)
 {
-	unmask_irq(vector);
+	unmask_irq(irq);
 	/*
 	 * IOSAPIC simply drops interrupts pended while the
 	 * corresponding pin was masked, so we can't know if an
@@ -264,15 +262,16 @@
 }
 
 static void
-iosapic_ack_edge_irq (unsigned int vector)
+iosapic_ack_edge_irq (unsigned int irq)
 {
+	irq_desc_t *idesc = irq_desc(irq);
 	/*
 	 * Once we have recorded IRQ_PENDING already, we can mask the
 	 * interrupt for real. This prevents IRQ storms from unhandled
 	 * devices.
 	 */
-	if ((irq_desc[vector].status & (IRQ_PENDING|IRQ_DISABLED)) == (IRQ_PENDING|IRQ_DISABLED))
-		mask_irq(vector);
+	if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) == (IRQ_PENDING|IRQ_DISABLED))
+		mask_irq(irq);
 }
 
 #define iosapic_enable_edge_irq		unmask_irq
@@ -291,7 +290,7 @@
 };
 
 static unsigned int
-iosapic_version (char *addr) 
+iosapic_version (char *addr)
 {
 	/*
 	 * IOSAPIC Version Register return 32 bit structure like:
@@ -335,6 +334,7 @@
 {
 	struct hw_interrupt_type *irq_type;
 	int i, irq, max_pin, vector;
+	irq_desc_t *idesc;
 	unsigned int ver;
 	char *addr;
 	static int first_time = 1;
@@ -342,18 +342,18 @@
 	if (first_time) {
 		first_time = 0;
 
-		for (vector = 0; vector < NR_IRQS; ++vector)
+		for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
 			iosapic_irq[vector].pin = -1;	/* mark as unused */
 
-		/* 
+		/*
 		 * Fetch the PCI interrupt routing table:
 		 */
 #ifdef CONFIG_ACPI_KERNEL_CONFIG
 		acpi_cf_get_pci_vectors(&pci_irq.route, &pci_irq.num_routes);
 #else
 		pci_irq.route =
-			(struct pci_vector_struct *) __va(ia64_boot_param.pci_vectors);
-		pci_irq.num_routes = ia64_boot_param.num_pci_vectors;
+			(struct pci_vector_struct *) __va(ia64_boot_param->pci_vectors);
+		pci_irq.num_routes = ia64_boot_param->num_pci_vectors;
 #endif
 	}
 
@@ -361,8 +361,8 @@
 
 	ver = iosapic_version(addr);
 	max_pin = (ver >> 16) & 0xff;
-	
-	printk("IOSAPIC: version %x.%x, address 0x%lx, IRQs 0x%02x-0x%02x\n", 
+
+	printk("IOSAPIC: version %x.%x, address 0x%lx, IRQs 0x%02x-0x%02x\n",
 	       (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, base_irq, base_irq + max_pin);
 
 	if (base_irq == 0)
@@ -385,20 +385,20 @@
 			       irq, iosapic_irq[vector].base_irq + iosapic_irq[vector].pin,
 			       vector);
 #endif
-		  	irq_type = &irq_type_iosapic_edge;
-			if (irq_desc[vector].handler != irq_type) {
-				if (irq_desc[vector].handler != &no_irq_type)
+			irq_type = &irq_type_iosapic_edge;
+			idesc = irq_desc(vector);
+			if (idesc->handler != irq_type) {
+				if (idesc->handler != &no_irq_type)
 					printk("iosapic_init: changing vector 0x%02x from %s to "
-					       "%s\n", irq, irq_desc[vector].handler->typename,
+					       "%s\n", irq, idesc->handler->typename,
 					       irq_type->typename);
-				irq_desc[vector].handler = irq_type;
+				idesc->handler = irq_type;
 			}
 
 			/* program the IOSAPIC routing table: */
 			set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
 		}
 
-#ifndef CONFIG_IA64_SOFTSDV_HACKS
 	for (i = 0; i < pci_irq.num_routes; i++) {
 		irq = pci_irq.route[i].irq;
 
@@ -428,18 +428,17 @@
 		       iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, vector);
 # endif
 		irq_type = &irq_type_iosapic_level;
-		if (irq_desc[vector].handler != irq_type){
-			if (irq_desc[vector].handler != &no_irq_type)
+		idesc = irq_desc(vector);
+		if (idesc->handler != irq_type){
+			if (idesc->handler != &no_irq_type)
 				printk("iosapic_init: changing vector 0x%02x from %s to %s\n",
-				       vector, irq_desc[vector].handler->typename,
-				       irq_type->typename);
-			irq_desc[vector].handler = irq_type;
+				       vector, idesc->handler->typename, irq_type->typename);
+			idesc->handler = irq_type;
 		}
 
 		/* program the IOSAPIC routing table: */
 		set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
 	}
-#endif /* !CONFIG_IA64_SOFTSDV_HACKS */
 }
 
 void
@@ -492,7 +491,7 @@
 		 * Nothing to fixup
 		 * Fix out-of-range IRQ numbers
 		 */
-		if (dev->irq >= NR_IRQS)
+		if (dev->irq >= IA64_NUM_VECTORS)
 			dev->irq = 15;	/* Spurious interrupts */
 	}
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/irq.c linux/arch/ia64/kernel/irq.c
--- v2.4.3/linux/arch/ia64/kernel/irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ia64/kernel/irq.c	Thu Apr  5 12:51:47 2001
@@ -63,7 +63,7 @@
 /*
  * Controller mappings for all interrupt sources:
  */
-irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
+irq_desc_t _irq_desc[NR_IRQS] __cacheline_aligned =
 	{ [0 ... NR_IRQS-1] = { IRQ_DISABLED, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};
 
 static void register_irq_proc (unsigned int irq);
@@ -131,6 +131,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	irq_desc_t *idesc;
 	char *p = buf;
 
 	p += sprintf(p, "           ");
@@ -139,8 +140,9 @@
 	*p++ = '\n';
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
-		action = irq_desc[i].action;
-		if (!action) 
+		idesc = irq_desc(i);
+		action = idesc->action;
+		if (!action)
 			continue;
 		p += sprintf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
@@ -150,7 +152,7 @@
 			p += sprintf(p, "%10u ",
 				kstat.irqs[cpu_logical_map(j)][i]);
 #endif
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
+		p += sprintf(p, " %14s", idesc->handler->typename);
 		p += sprintf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -193,10 +195,10 @@
 	printk("\n%s, CPU %d:\n", str, cpu);
 	printk("irq:  %d [",irqs_running());
 	for(i=0;i < smp_num_cpus;i++)
-		printk(" %d",local_irq_count(i));
+		printk(" %d",irq_count(i));
 	printk(" ]\nbh:   %d [",spin_is_locked(&global_bh_lock) ? 1 : 0);
 	for(i=0;i < smp_num_cpus;i++)
-		printk(" %d",local_bh_count(i));
+		printk(" %d",bh_count(i));
 
 	printk(" ]\nStack dumps:");
 #if defined(__ia64__)
@@ -224,7 +226,7 @@
 		esp &= ~(THREAD_SIZE-1);
 		esp += sizeof(struct task_struct);
 		show_stack((void*)esp);
- 	}
+	}
 #else
 	You lose...
 #endif
@@ -232,7 +234,7 @@
 	show_stack(NULL);
 	printk("\n");
 }
-	
+
 #define MAXCOUNT 100000000
 
 /*
@@ -266,7 +268,7 @@
 # endif
 #endif
 
-static inline void wait_on_irq(int cpu)
+static inline void wait_on_irq(void)
 {
 	int count = MAXCOUNT;
 
@@ -278,7 +280,7 @@
 		 * already executing in one..
 		 */
 		if (!irqs_running())
-			if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock))
+			if (local_bh_count() || !spin_is_locked(&global_bh_lock))
 				break;
 
 		/* Duh, we have to loop. Release the lock to avoid deadlocks */
@@ -290,13 +292,13 @@
 				count = ~0;
 			}
 			__sti();
-			SYNC_OTHER_CORES(cpu);
+			SYNC_OTHER_CORES(smp_processor_id());
 			__cli();
 			if (irqs_running())
 				continue;
 			if (global_irq_lock)
 				continue;
-			if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock))
+			if (!local_bh_count() && spin_is_locked(&global_bh_lock))
 				continue;
 			if (!test_and_set_bit(0,&global_irq_lock))
 				break;
@@ -320,28 +322,28 @@
 	}
 }
 
-static inline void get_irqlock(int cpu)
+static inline void get_irqlock(void)
 {
 	if (test_and_set_bit(0,&global_irq_lock)) {
 		/* do we already hold the lock? */
-		if (cpu == global_irq_holder)
+		if (smp_processor_id() == global_irq_holder)
 			return;
 		/* Uhhuh.. Somebody else got it. Wait.. */
 		do {
 			do {
 			} while (test_bit(0,&global_irq_lock));
-		} while (test_and_set_bit(0,&global_irq_lock));		
+		} while (test_and_set_bit(0,&global_irq_lock));
 	}
-	/* 
+	/*
 	 * We also to make sure that nobody else is running
-	 * in an interrupt context. 
+	 * in an interrupt context.
 	 */
-	wait_on_irq(cpu);
+	wait_on_irq();
 
 	/*
 	 * Ok, finally..
 	 */
-	global_irq_holder = cpu;
+	global_irq_holder = smp_processor_id();
 }
 
 #define EFLAGS_IF_SHIFT 9
@@ -365,28 +367,24 @@
 #ifdef __ia64__
 	__save_flags(flags);
 	if (flags & IA64_PSR_I) {
-		int cpu = smp_processor_id();
 		__cli();
-		if (!local_irq_count(cpu))
-			get_irqlock(cpu);
+		if (!local_irq_count())
+			get_irqlock();
 	}
 #else
 	__save_flags(flags);
 	if (flags & (1 << EFLAGS_IF_SHIFT)) {
-		int cpu = smp_processor_id();
 		__cli();
-		if (!local_irq_count(cpu))
-			get_irqlock(cpu);
+		if (!local_irq_count())
+			get_irqlock();
 	}
 #endif
 }
 
 void __global_sti(void)
 {
-	int cpu = smp_processor_id();
-
-	if (!local_irq_count(cpu))
-		release_irqlock(cpu);
+	if (!local_irq_count())
+		release_irqlock(smp_processor_id());
 	__sti();
 }
 
@@ -414,7 +412,7 @@
 	retval = 2 + local_enabled;
 
 	/* check for global flags if we're not in an interrupt */
-	if (!local_irq_count(cpu)) {
+	if (!local_irq_count()) {
 		if (local_enabled)
 			retval = 1;
 		if (global_irq_holder == cpu)
@@ -456,9 +454,8 @@
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status;
-	int cpu = smp_processor_id();
 
-	irq_enter(cpu, irq);
+	local_irq_enter(irq);
 
 	status = 1;	/* Force the "do bottom halves" bit */
 
@@ -474,7 +471,7 @@
 		add_interrupt_randomness(irq);
 	__cli();
 
-	irq_exit(cpu, irq);
+	local_irq_exit(irq);
 
 	return status;
 }
@@ -483,11 +480,11 @@
  * 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. 
+ * controller lock.
  */
 void inline disable_irq_nosync(unsigned int irq)
 {
-	irq_desc_t *desc = irq_desc + irq;
+	irq_desc_t *desc = irq_desc(irq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -507,17 +504,17 @@
 	disable_irq_nosync(irq);
 
 #ifdef CONFIG_SMP
-	if (!local_irq_count(smp_processor_id())) {
+	if (!local_irq_count()) {
 		do {
 			barrier();
-		} while (irq_desc[irq].status & IRQ_INPROGRESS);
+		} while (irq_desc(irq)->status & IRQ_INPROGRESS);
 	}
 #endif
 }
 
 void enable_irq(unsigned int irq)
 {
-	irq_desc_t *desc = irq_desc + irq;
+	irq_desc_t *desc = irq_desc(irq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -541,26 +538,14 @@
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
-void do_IRQ_per_cpu(unsigned long irq, struct pt_regs *regs)
-{
-	irq_desc_t *desc = irq_desc + irq;
-	int cpu = smp_processor_id();
-
-	kstat.irqs[cpu][irq]++;
-
-	desc->handler->ack(irq);
-	handle_IRQ_event(irq, regs, desc->action);
-	desc->handler->end(irq);
-}
-
 /*
  * do_IRQ handles all normal device IRQ's (the special
  * SMP cross-CPU interrupts have their own specific
  * handlers).
  */
 unsigned int do_IRQ(unsigned long 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
@@ -571,75 +556,82 @@
 	 * handled by some other CPU. (or is disabled)
 	 */
 	int cpu = smp_processor_id();
-	irq_desc_t *desc = irq_desc + irq;
+	irq_desc_t *desc = irq_desc(irq);
 	struct irqaction * action;
 	unsigned int status;
 
 	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 (desc->status & IRQ_PER_CPU) {
+		/* no locking required for CPU-local interrupts: */
+		desc->handler->ack(irq);
+		handle_IRQ_event(irq, regs, desc->action);
+		desc->handler->end(irq);
+	} else {
+		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 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 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;
 
-	/*
-	 * 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 (;;) {
+		/*
+		 * 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;
+
+		/*
+		 * 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;
+		}
+		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);
-		handle_IRQ_event(irq, regs, action);
-		spin_lock(&desc->lock);
-		
-		if (!(desc->status & IRQ_PENDING))
-			break;
-		desc->status &= ~IRQ_PENDING;
 	}
-	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);
-
 	return 1;
 }
 
-int request_irq(unsigned int irq, 
+int request_irq(unsigned int irq,
 		void (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags, 
+		unsigned long irqflags,
 		const char * devname,
 		void *dev_id)
 {
@@ -655,7 +647,7 @@
 	 */
 	if (irqflags & SA_SHIRQ) {
 		if (!dev_id)
-			printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
+			printk("Bad boy: %s called us without a dev_id!\n", devname);
 	}
 #endif
 
@@ -681,7 +673,7 @@
 		kfree(action);
 	return retval;
 }
-		
+
 void free_irq(unsigned int irq, void *dev_id)
 {
 	irq_desc_t *desc;
@@ -691,7 +683,7 @@
 	if (irq >= NR_IRQS)
 		return;
 
-	desc = irq_desc + irq;
+	desc = irq_desc(irq);
 	spin_lock_irqsave(&desc->lock,flags);
 	p = &desc->action;
 	for (;;) {
@@ -739,16 +731,16 @@
 	unsigned long val;
 	unsigned long delay;
 
-	/* 
+	/*
 	 * something may have generated an irq long ago and we want to
-	 * flush such a longstanding irq before considering it as spurious. 
+	 * flush such a longstanding irq before considering it as spurious.
 	 */
 	for (i = NR_IRQS-1; i > 0; i--)  {
-		desc = irq_desc + i;
+		desc = irq_desc(i);
 
 		spin_lock_irq(&desc->lock);
-		if (!irq_desc[i].action) 
-			irq_desc[i].handler->startup(i);
+		if (!desc->action)
+			desc->handler->startup(i);
 		spin_unlock_irq(&desc->lock);
 	}
 
@@ -762,7 +754,7 @@
 	 * happened in the previous stage, it may have masked itself)
 	 */
 	for (i = NR_IRQS-1; i > 0; i--) {
-		desc = irq_desc + i;
+		desc = irq_desc(i);
 
 		spin_lock_irq(&desc->lock);
 		if (!desc->action) {
@@ -784,7 +776,7 @@
 	 */
 	val = 0;
 	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc_t *desc = irq_desc + i;
+		irq_desc_t *desc = irq_desc(i);
 		unsigned int status;
 
 		spin_lock_irq(&desc->lock);
@@ -816,7 +808,7 @@
 
 	mask = 0;
 	for (i = 0; i < 16; i++) {
-		irq_desc_t *desc = irq_desc + i;
+		irq_desc_t *desc = irq_desc(i);
 		unsigned int status;
 
 		spin_lock_irq(&desc->lock);
@@ -846,7 +838,7 @@
 	nr_irqs = 0;
 	irq_found = 0;
 	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc_t *desc = irq_desc + i;
+		irq_desc_t *desc = irq_desc(i);
 		unsigned int status;
 
 		spin_lock_irq(&desc->lock);
@@ -869,13 +861,12 @@
 	return irq_found;
 }
 
-/* this was setup_x86_irq but it seems pretty generic */
 int setup_irq(unsigned int irq, struct irqaction * new)
 {
 	int shared = 0;
 	unsigned long flags;
 	struct irqaction *old, **p;
-	irq_desc_t *desc = irq_desc + irq;
+	irq_desc_t *desc = irq_desc(irq);
 
 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
@@ -986,7 +977,7 @@
 	int irq = (long) data, full_count = count, err;
 	unsigned long new_value;
 
-	if (!irq_desc[irq].handler->set_affinity)
+	if (!irq_desc(irq)->handler->set_affinity)
 		return -EIO;
 
 	err = parse_hex_value(buffer, count, &new_value);
@@ -1002,7 +993,7 @@
 #endif
 
 	irq_affinity[irq] = new_value;
-	irq_desc[irq].handler->set_affinity(irq, new_value);
+	irq_desc(irq)->handler->set_affinity(irq, new_value);
 
 	return full_count;
 }
@@ -1037,7 +1028,7 @@
 	struct proc_dir_entry *entry;
 	char name [MAX_NAMELEN];
 
-	if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type))
+	if (!root_irq_dir || (irq_desc(irq)->handler == &no_irq_type))
 		return;
 
 	memset(name, 0, MAX_NAMELEN);
@@ -1079,9 +1070,8 @@
 	 * Create entries for all existing IRQs.
 	 */
 	for (i = 0; i < NR_IRQS; i++) {
-		if (irq_desc[i].handler == &no_irq_type)
+		if (irq_desc(i)->handler == &no_irq_type)
 			continue;
 		register_irq_proc(i);
 	}
 }
-
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/irq_ia64.c linux/arch/ia64/kernel/irq_ia64.c
--- v2.4.3/linux/arch/ia64/kernel/irq_ia64.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ia64/kernel/irq_ia64.c	Thu Apr  5 12:51:47 2001
@@ -39,7 +39,7 @@
 #define IRQ_DEBUG	0
 
 /* default base addr of IPI table */
-unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IPI_DEFAULT_BASE_ADDR);	
+unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR);
 
 /*
  * Legacy IRQ to IA-64 vector translation table.
@@ -53,21 +53,23 @@
 int
 ia64_alloc_irq (void)
 {
-	static int next_irq = FIRST_DEVICE_IRQ;
+	static int next_irq = IA64_FIRST_DEVICE_VECTOR;
 
-	if (next_irq > LAST_DEVICE_IRQ)
+	if (next_irq > IA64_LAST_DEVICE_VECTOR)
 		/* XXX could look for sharable vectors instead of panic'ing... */
 		panic("ia64_alloc_irq: out of interrupt vectors!");
 	return next_irq++;
 }
 
+extern unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs);
+
 /*
  * That's where the IVT branches when we get an external
  * interrupt. This branches to the correct hardware IRQ handler via
  * function ptr.
  */
 void
-ia64_handle_irq (unsigned long vector, struct pt_regs *regs)
+ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
 {
 	unsigned long saved_tpr;
 
@@ -89,7 +91,7 @@
 			static unsigned char count;
 			static long last_time;
 
-			if (count > 5 && jiffies - last_time > 5*HZ)
+			if (jiffies - last_time > 5*HZ)
 				count = 0;
 			if (++count < 5) {
 				last_time = jiffies;
@@ -109,19 +111,10 @@
 	saved_tpr = ia64_get_tpr();
 	ia64_srlz_d();
 	do {
-		if (vector >= NR_IRQS) {
-			printk("handle_irq: invalid vector %lu\n", vector);
-			ia64_set_tpr(saved_tpr);
-			ia64_srlz_d();
-			return;
-		}
 		ia64_set_tpr(vector);
 		ia64_srlz_d();
 
-		if ((irq_desc[vector].status & IRQ_PER_CPU) != 0)
-			do_IRQ_per_cpu(vector, regs);
-		else
-			do_IRQ(vector, regs);
+		do_IRQ(local_vector_to_irq(vector), regs);
 
 		/*
 		 * Disable interrupts and send EOI:
@@ -130,7 +123,7 @@
 		ia64_set_tpr(saved_tpr);
 		ia64_eoi();
 		vector = ia64_get_ivr();
-	} while (vector != IA64_SPURIOUS_INT);
+	} while (vector != IA64_SPURIOUS_INT_VECTOR);
 }
 
 #ifdef CONFIG_SMP
@@ -144,33 +137,30 @@
 };
 #endif
 
+void
+register_percpu_irq (ia64_vector vec, struct irqaction *action)
+{
+	irq_desc_t *desc;
+	unsigned int irq;
+
+	for (irq = 0; irq < NR_IRQS; ++irq)
+		if (irq_to_vector(irq) == vec) {
+			desc = irq_desc(irq);
+			desc->status |= IRQ_PER_CPU;
+			desc->handler = &irq_type_ia64_sapic;
+			if (action)
+				setup_irq(irq, action);
+		}
+}
+
 void __init
 init_IRQ (void)
 {
-	/*
-	 * Disable all local interrupts
-	 */
-	ia64_set_itv(0, 1);
-	ia64_set_lrr0(0, 1);
-	ia64_set_lrr1(0, 1);
-
-	irq_desc[IA64_SPURIOUS_INT].handler = &irq_type_ia64_sapic;
+	register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
 #ifdef CONFIG_SMP
-	/* 
-	 * Configure the IPI vector and handler
-	 */
-	irq_desc[IPI_IRQ].status |= IRQ_PER_CPU;
-	irq_desc[IPI_IRQ].handler = &irq_type_ia64_sapic;
-	setup_irq(IPI_IRQ, &ipi_irqaction);
+	register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
 #endif
-
-	ia64_set_pmv(1 << 16);
-	ia64_set_cmcv(CMC_IRQ);			/* XXX fix me */
-
 	platform_irq_init();
-
-	/* clear TPR to enable all interrupt classes: */
-	ia64_set_tpr(0);
 }
 
 void
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/ivt.S linux/arch/ia64/kernel/ivt.S
--- v2.4.3/linux/arch/ia64/kernel/ivt.S	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/ivt.S	Thu Apr  5 12:51:47 2001
@@ -1,9 +1,9 @@
 /*
  * arch/ia64/kernel/ivt.S
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
  * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1998-2000 David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 David Mosberger <davidm@hpl.hp.com>
  *
  * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
  * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
@@ -14,7 +14,7 @@
  *
  * External interrupts only use 1 entry. All others are internal interrupts
  *
- * The first 20 entries of the table contain 64 bundles each while the 
+ * The first 20 entries of the table contain 64 bundles each while the
  * remaining 48 entries contain only 16 bundles each.
  *
  * The 64 bundles are used to allow inlining the whole handler for critical
@@ -22,7 +22,7 @@
  *
  *  For each entry, the comment is as follows:
  *
- * 		// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ *		// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
  *  entry offset ----/     /         /                  /          /
  *  entry number ---------/         /                  /          /
  *  size of the entry -------------/                  /          /
@@ -37,7 +37,9 @@
 
 #include <linux/config.h>
 
+#include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/kregs.h>
 #include <asm/offsets.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -45,6 +47,22 @@
 #include <asm/system.h>
 #include <asm/unistd.h>
 
+#if 1
+# define PSR_DEFAULT_BITS	psr.ac
+#else
+# define PSR_DEFAULT_BITS	0
+#endif
+
+#if 0
+  /*
+   * This lets you track the last eight faults that occurred on the CPU.  Make sure ar.k2 isn't
+   * needed for something else before enabling this...
+   */
+# define DBG_FAULT(i)	mov r16=ar.k2;;	shl r16=r16,8;;	add r16=(i),r16;;mov ar.k2=r16
+#else
+# define DBG_FAULT(i)
+#endif
+
 #define MINSTATE_VIRT	/* needed by minstate.h */
 #include "minstate.h"
 
@@ -57,8 +75,8 @@
  * As we don't (hopefully) use the space available, we need to fill it with
  * nops. the parameter may be used for debugging and is representing the entry
  * number
- */ 
-#define BREAK_BUNDLE(a) 	break.m (a); \
+ */
+#define BREAK_BUNDLE(a)	break.m (a); \
 				break.i (a); \
 				break.i (a)
 /*
@@ -71,17 +89,15 @@
  */
 #define BREAK_BUNDLE8(a); BREAK_BUNDLE4(a); BREAK_BUNDLE4(a)
 
-	.psr abi64
-	.psr lsb
-	.lsb
-
-	.section __ivt_section,"ax"
+	.section .text.ivt,"ax"
 
 	.align 32768	// align on 32KB boundary
 	.global ia64_ivt
 ia64_ivt:
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
+ENTRY(vhpt_miss)
+	DBG_FAULT(0)
 	/*
 	 * The VHPT vector is invoked when the TLB entry for the virtual page table
 	 * is missing.  This happens only as a result of a previous
@@ -103,7 +119,7 @@
 	;;
 	rsm psr.dt				// use physical addressing for data
 	mov r31=pr				// save the predicate registers
-	mov r19=ar.k7				// get page table base address
+	mov r19=IA64_KR(PT_BASE)		// get page table base address
 	shl r21=r16,3				// shift bit 60 into sign bit
 	shr.u r17=r16,61			// get the region number into r17
 	;;
@@ -146,19 +162,21 @@
 (p6)	br.spnt.many page_fault			// handle bad address/page not present (page fault)
 	mov cr.ifa=r22
 
-	// Now compute and insert the TLB entry for the virtual page table.
-	// We never execute in a page table page so there is no need to set
-	// the exception deferral bit.
+	/*
+	 * Now compute and insert the TLB entry for the virtual page table.  We never
+	 * execute in a page table page so there is no need to set the exception deferral
+	 * bit.
+	 */
 	adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
 	;;
 (p7)	itc.d r24
 	;;
 #ifdef CONFIG_SMP
-	//
-	// Re-check L2 and L3 pagetable.  If they changed, we may have received
-	// a ptc.g between reading the pagetable and the "itc".  If so,
-	// flush the entry we inserted and retry.
-	//
+	/*
+	 * Re-check L2 and L3 pagetable.  If they changed, we may have received a ptc.g
+	 * between reading the pagetable and the "itc".  If so, flush the entry we
+	 * inserted and retry.
+	 */
 	ld8 r25=[r21]				// read L3 PTE again
 	ld8 r26=[r17]				// read L2 entry again
 	;;
@@ -173,26 +191,29 @@
 
 	mov pr=r31,-1				// restore predicate registers
 	rfi
-	;;
+END(vhpt_miss)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x0400 Entry 1 (size 64 bundles) ITLB (21)
+ENTRY(itlb_miss)
+	DBG_FAULT(1)
 	/*
 	 * The ITLB handler accesses the L3 PTE via the virtually mapped linear
 	 * page table.  If a nested TLB miss occurs, we switch into physical
 	 * mode, walk the page table, and then re-execute the L3 PTE read
 	 * and go on normally after that.
 	 */
-itlb_fault:
 	mov r16=cr.ifa				// get virtual address
 	mov r29=b0				// save b0
 	mov r31=pr				// save predicates
+itlb_fault:
 	mov r17=cr.iha				// get virtual address of L3 PTE
 	movl r30=1f				// load nested fault continuation point
 	;;
 1:	ld8 r18=[r17]				// read L3 PTE
 	;;
+	mov b0=r29
 	tbit.z p6,p0=r18,_PAGE_P_BIT		// page present bit cleared?
 (p6)	br.cond.spnt.many page_fault
 	;;
@@ -208,26 +229,29 @@
 #endif
 	mov pr=r31,-1
 	rfi
-	;;
+END(itlb_miss)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
+ENTRY(dtlb_miss)
+	DBG_FAULT(2)
 	/*
 	 * The DTLB handler accesses the L3 PTE via the virtually mapped linear
 	 * page table.  If a nested TLB miss occurs, we switch into physical
 	 * mode, walk the page table, and then re-execute the L3 PTE read
 	 * and go on normally after that.
 	 */
-dtlb_fault:
 	mov r16=cr.ifa				// get virtual address
 	mov r29=b0				// save b0
 	mov r31=pr				// save predicates
+dtlb_fault:
 	mov r17=cr.iha				// get virtual address of L3 PTE
 	movl r30=1f				// load nested fault continuation point
 	;;
 1:	ld8 r18=[r17]				// read L3 PTE
 	;;
+	mov b0=r29
 	tbit.z p6,p0=r18,_PAGE_P_BIT		// page present bit cleared?
 (p6)	br.cond.spnt.many page_fault
 	;;
@@ -243,24 +267,27 @@
 #endif
 	mov pr=r31,-1
 	rfi
-	;;
+END(dtlb_miss)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
+ENTRY(alt_itlb_miss)
+	DBG_FAULT(3)
 	mov r16=cr.ifa		// get address that caused the TLB miss
-	movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX
+	movl r17=PAGE_KERNEL
 	mov r21=cr.ipsr
 	mov r31=pr
 	;;
 #ifdef CONFIG_DISABLE_VHPT
 	shr.u r22=r16,61			// get the region number into r21
 	;;
-	cmp.gt p8,p0=6,r22			// user mode 
+	cmp.gt p8,p0=6,r22			// user mode
 	;;
 (p8)	thash r17=r16
 	;;
 (p8)	mov cr.iha=r17
+(p8)	mov r29=b0				// save b0
 (p8)	br.cond.dptk.many itlb_fault
 #endif
 	extr.u r23=r21,IA64_PSR_CPL0_BIT,2	// extract psr.cpl
@@ -277,13 +304,15 @@
 	itc.i r19		// insert the TLB entry
 	mov pr=r31,-1
 	rfi
-	;;
+END(alt_itlb_miss)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
+ENTRY(alt_dtlb_miss)
+	DBG_FAULT(4)
 	mov r16=cr.ifa		// get address that caused the TLB miss
-	movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX
+	movl r17=PAGE_KERNEL
 	mov r20=cr.isr
 	mov r21=cr.ipsr
 	mov r31=pr
@@ -296,6 +325,7 @@
 (p8)	thash r17=r16
 	;;
 (p8)	mov cr.iha=r17
+(p8)	mov r29=b0				// save b0
 (p8)	br.cond.dptk.many dtlb_fault
 #endif
 	extr.u r23=r21,IA64_PSR_CPL0_BIT,2	// extract psr.cpl
@@ -316,70 +346,63 @@
 (p7)	itc.d r19		// insert the TLB entry
 	mov pr=r31,-1
 	rfi
-	;;
+END(alt_dtlb_miss)
 
 	//-----------------------------------------------------------------------------------
 	// call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
-page_fault:
+ENTRY(page_fault)
 	ssm psr.dt
 	;;
 	srlz.i
 	;;
 	SAVE_MIN_WITH_COVER
-	//
-	// Copy control registers to temporary registers, then turn on psr bits,
-	// then copy the temporary regs to the output regs.  We have to do this
-	// because the "alloc" can cause a mandatory store which could lead to
-	// an "Alt DTLB" fault which we can handle only if psr.ic is on.
-	//
-	mov r8=cr.ifa
-	mov r9=cr.isr
+	alloc r15=ar.pfs,0,0,3,0
+	mov out0=cr.ifa
+	mov out1=cr.isr
 	adds r3=8,r2				// set up second base pointer
 	;;
-	ssm psr.ic
+	ssm psr.ic | PSR_DEFAULT_BITS
 	;;
 	srlz.i					// guarantee that interrupt collection is enabled
 	;;
 (p15)	ssm psr.i				// restore psr.i
 	movl r14=ia64_leave_kernel
 	;;
-	alloc r15=ar.pfs,0,0,3,0		// must be first in insn group
-	mov out0=r8
-	mov out1=r9
-	;;
 	SAVE_REST
 	mov rp=r14
 	;;
 	adds out2=16,r12			// out2 = pointer to pt_regs
 	br.call.sptk.many b6=ia64_do_page_fault	// ignore return address
-	;;
+END(page_fault)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
-	//
-	// In the absence of kernel bugs, we get here when the virtually mapped linear page
-	// table is accessed non-speculatively (e.g.,  in the Dirty-bit, Instruction
-	// Access-bit, or Data Access-bit faults).  If the DTLB entry for the virtual page
-	// table is missing, a nested TLB miss fault is triggered and control is transferred
-	// to this point.  When this happens, we lookup the pte for the faulting address
-	// by walking the page table in physical mode and return to the continuation point
-	// passed in register r30 (or call page_fault if the address is not mapped).
-	//
-	// Input:	r16:	faulting address
-	//		r29:	saved b0
-	//		r30:	continuation address
-	//		r31:	saved pr
-	//
-	// Output:	r17:	physical address of L3 PTE of faulting address
-	//		r29:	saved b0
-	//		r30:	continuation address
-	//		r31:	saved pr
-	//
-	// Clobbered:	b0, r18, r19, r21, psr.dt (cleared)
-	//
+ENTRY(nested_dtlb_miss)
+	/*
+	 * In the absence of kernel bugs, we get here when the virtually mapped linear
+	 * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
+	 * Access-bit, or Data Access-bit faults).  If the DTLB entry for the virtual page
+	 * table is missing, a nested TLB miss fault is triggered and control is
+	 * transferred to this point.  When this happens, we lookup the pte for the
+	 * faulting address by walking the page table in physical mode and return to the
+	 * continuation point passed in register r30 (or call page_fault if the address is
+	 * not mapped).
+	 *
+	 * Input:	r16:	faulting address
+	 *		r29:	saved b0
+	 *		r30:	continuation address
+	 *		r31:	saved pr
+	 *
+	 * Output:	r17:	physical address of L3 PTE of faulting address
+	 *		r29:	saved b0
+	 *		r30:	continuation address
+	 *		r31:	saved pr
+	 *
+	 * Clobbered:	b0, r18, r19, r21, psr.dt (cleared)
+	 */
 	rsm psr.dt				// switch to using physical data addressing
-	mov r19=ar.k7				// get the page table base address
+	mov r19=IA64_KR(PT_BASE)		// get the page table base address
 	shl r21=r16,3				// shift bit 60 into sign bit
 	;;
 	shr.u r17=r16,61			// get the region number into r17
@@ -399,7 +422,6 @@
 	shr.u r18=r16,PMD_SHIFT			// shift L2 index into position
 	;;
 	ld8 r17=[r17]				// fetch the L1 entry (may be 0)
-	mov b0=r30
 	;;
 (p7)	cmp.eq p6,p7=r17,r0			// was L1 entry NULL?
 	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// compute address of L2 page table entry
@@ -409,34 +431,41 @@
 	;;
 (p7)	cmp.eq.or.andcm p6,p7=r17,r0		// was L2 entry NULL?
 	dep r17=r19,r17,3,(PAGE_SHIFT-3)	// compute address of L3 page table entry
-	;;
 (p6)	br.cond.spnt.many page_fault
+	mov b0=r30
 	br.sptk.many b0				// return to continuation point
-	;;
+END(nested_dtlb_miss)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
+ENTRY(ikey_miss)
+	DBG_FAULT(6)
 	FAULT(6)
+END(ikey_miss)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ENTRY(dkey_miss)
+	DBG_FAULT(7)
 	FAULT(7)
+END(dkey_miss)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
-	//
-	// What we do here is to simply turn on the dirty bit in the PTE.  We need
-	// to update both the page-table and the TLB entry.  To efficiently access
-	// the PTE, we address it through the virtual page table.  Most likely, the
-	// TLB entry for the relevant virtual page table page is still present in
-	// the TLB so we can normally do this without additional TLB misses.
-	// In case the necessary virtual page table TLB entry isn't present, we take
-	// a nested TLB miss hit where we look up the physical address of the L3 PTE
-	// and then continue at label 1 below.
-	//
+ENTRY(dirty_bit)
+	DBG_FAULT(8)
+	/*
+	 * What we do here is to simply turn on the dirty bit in the PTE.  We need to
+	 * update both the page-table and the TLB entry.  To efficiently access the PTE,
+	 * we address it through the virtual page table.  Most likely, the TLB entry for
+	 * the relevant virtual page table page is still present in the TLB so we can
+	 * normally do this without additional TLB misses.  In case the necessary virtual
+	 * page table TLB entry isn't present, we take a nested TLB miss hit where we look
+	 * up the physical address of the L3 PTE and then continue at label 1 below.
+	 */
 	mov r16=cr.ifa				// get the address that caused the fault
 	movl r30=1f				// load continuation point in case of nested fault
 	;;
@@ -477,11 +506,13 @@
 #endif
 	mov pr=r31,-1				// restore pr
 	rfi
-	;;
+END(idirty_bit)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
+ENTRY(iaccess_bit)
+	DBG_FAULT(9)
 	// Like Entry 8, except for instruction access
 	mov r16=cr.ifa				// get the address that caused the fault
 	movl r30=1f				// load continuation point in case of nested fault
@@ -504,14 +535,14 @@
 	mov r28=ar.ccv				// save ar.ccv
 	;;
 1:	ld8 r18=[r17]
+	;;
 # if defined(CONFIG_IA32_SUPPORT) && \
     (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_B0_SPECIFIC))
-	//
-	// Erratum 85 (Access bit fault could be reported before page not present fault)
-	//   If the PTE is indicates the page is not present, then just turn this into a
-	//   page fault.
-	//
-	;;
+	/*
+	 * Erratum 85 (Access bit fault could be reported before page not present fault)
+	 *   If the PTE is indicates the page is not present, then just turn this into a
+	 *   page fault.
+	 */
 	tbit.z p6,p0=r18,_PAGE_P_BIT		// page present bit cleared?
 (p6)	br.sptk page_fault			// page wasn't present
 # endif
@@ -538,11 +569,11 @@
 	;;
 # if defined(CONFIG_IA32_SUPPORT) && \
     (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_B0_SPECIFIC))
-	//
-	// Erratum 85 (Access bit fault could be reported before page not present fault)
-	//   If the PTE is indicates the page is not present, then just turn this into a
-	//   page fault.
-	//
+	/*
+	 * Erratum 85 (Access bit fault could be reported before page not present fault)
+	 *   If the PTE is indicates the page is not present, then just turn this into a
+	 *   page fault.
+	 */
 	tbit.z p6,p0=r18,_PAGE_P_BIT		// page present bit cleared?
 (p6)	br.sptk page_fault			// page wasn't present
 # endif
@@ -554,11 +585,13 @@
 #endif /* !CONFIG_SMP */
 	mov pr=r31,-1
 	rfi
-	;;
+END(iaccess_bit)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
+ENTRY(daccess_bit)
+	DBG_FAULT(10)
 	// Like Entry 8, except for data access
 	mov r16=cr.ifa				// get the address that caused the fault
 	movl r30=1f				// load continuation point in case of nested fault
@@ -599,11 +632,13 @@
 	mov b0=r29				// restore b0
 	mov pr=r31,-1
 	rfi
-	;;
+END(daccess_bit)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
+ENTRY(break_fault)
+	DBG_FAULT(11)
 	mov r16=cr.iim
 	mov r17=__IA64_BREAK_SYSCALL
 	mov r31=pr		// prepare to save predicates
@@ -613,8 +648,7 @@
 
 	SAVE_MIN				// uses r31; defines r2:
 
-	// turn interrupt collection back on:
-	ssm psr.ic
+	ssm psr.ic | PSR_DEFAULT_BITS
 	;;
 	srlz.i					// guarantee that interrupt collection is enabled
 	cmp.eq pSys,pNonSys=r0,r0		// set pSys=1, pNonSys=0
@@ -667,12 +701,12 @@
 	;;
 	st8 [r16]=r18				// store new value for cr.isr
 
-(p8)	br.call.sptk.many b6=b6			// ignore this return addr 
+(p8)	br.call.sptk.many b6=b6			// ignore this return addr
 	br.call.sptk.many rp=ia64_trace_syscall	// rp will be overwritten (ignored)
 	// NOT REACHED
+END(break_fault)
 
-	.proc demine_args
-demine_args:
+ENTRY(demine_args)
 	alloc r2=ar.pfs,8,0,0,0
 	tnat.nz p8,p0=in0
 	tnat.nz p9,p0=in1
@@ -696,16 +730,18 @@
 (p14)	mov in6=-1
 (p15)	mov in7=-1
 	br.ret.sptk.many rp
-	.endp demine_args
+END(demine_args)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
+ENTRY(interrupt)
+	DBG_FAULT(12)
 	mov r31=pr		// prepare to save predicates
 	;;
 
 	SAVE_MIN_WITH_COVER	// uses r31; defines r2 and r3
-	ssm psr.ic		// turn interrupt collection
+	ssm psr.ic | PSR_DEFAULT_BITS
 	;;
 	adds r3=8,r2		// set up second base pointer for SAVE_REST
 	srlz.i			// ensure everybody knows psr.ic is back on
@@ -721,41 +757,38 @@
 	;;
 	mov rp=r14
 	br.call.sptk.many b6=ia64_handle_irq
-	;;
+END(interrupt)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x3400 Entry 13 (size 64 bundles) Reserved
+	DBG_FAULT(13)
 	FAULT(13)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x3800 Entry 14 (size 64 bundles) Reserved
+	DBG_FAULT(14)
 	FAULT(14)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x3c00 Entry 15 (size 64 bundles) Reserved
+	DBG_FAULT(15)
 	FAULT(15)
 
-//
-//  Squatting in this space ...
-//
-//  This special case dispatcher for illegal operation faults
-//  allows preserved registers to be modified through a 
-//  callback function (asm only) that is handed back from
-//  the fault handler in r8. Up to three arguments can be
-//  passed to the callback function by returning an aggregate
-//  with the callback as its first element, followed by the
-//  arguments.
-//
-dispatch_illegal_op_fault:
+	/*
+	 * Squatting in this space ...
+	 *
+	 * This special case dispatcher for illegal operation faults allows preserved
+	 * registers to be modified through a callback function (asm only) that is handed
+	 * back from the fault handler in r8. Up to three arguments can be passed to the
+	 * callback function by returning an aggregate with the callback as its first
+	 * element, followed by the arguments.
+	 */
+ENTRY(dispatch_illegal_op_fault)
 	SAVE_MIN_WITH_COVER
-	//
-	// The "alloc" can cause a mandatory store which could lead to
-	// an "Alt DTLB" fault which we can handle only if psr.ic is on.
-	//
-	ssm psr.ic
+	ssm psr.ic | PSR_DEFAULT_BITS
 	;;
 	srlz.i		// guarantee that interrupt collection is enabled
 	;;
@@ -781,27 +814,30 @@
 	cmp.ne p6,p0=0,r8
 (p6)	br.call.dpnt b6=b6		// call returns to ia64_leave_kernel
 	br.sptk ia64_leave_kernel
-	;;
+END(dispatch_illegal_op_fault)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x4000 Entry 16 (size 64 bundles) Reserved
+	DBG_FAULT(16)
 	FAULT(16)
 
 #ifdef CONFIG_IA32_SUPPORT
 
-	// There is no particular reason for this code to be here, other than that
-	// there happens to be space here that would go unused otherwise.  If this
-	// fault ever gets "unreserved", simply moved the following code to a more
-	// suitable spot...
+	/*
+	 * There is no particular reason for this code to be here, other than that
+	 * there happens to be space here that would go unused otherwise.  If this
+	 * fault ever gets "unreserved", simply moved the following code to a more
+	 * suitable spot...
+	 */
 
 	// IA32 interrupt entry point
 
-dispatch_to_ia32_handler:
+ENTRY(dispatch_to_ia32_handler)
 	SAVE_MIN
 	;;
 	mov r14=cr.isr
-	ssm psr.ic
+	ssm psr.ic | PSR_DEFAULT_BITS
 	;;
 	srlz.i					// guarantee that interrupt collection is enabled
 	;;
@@ -812,7 +848,7 @@
 	;;
 	mov r15=0x80
 	shr r14=r14,16          // Get interrupt number
-	;; 
+	;;
 	cmp.ne p6,p0=r14,r15
 (p6)    br.call.dpnt.many b6=non_ia32_syscall
 
@@ -823,7 +859,7 @@
 	st8 [r15]=r8		// save orignal EAX in r1 (IA32 procs don't use the GP)
 	;;
 	alloc r15=ar.pfs,0,0,6,0	// must first in an insn group
-	;; 
+	;;
 	ld4 r8=[r14],8          // r8 == EAX (syscall number)
 	mov r15=222		// sys_vfork - last implemented system call
 	;;
@@ -842,10 +878,10 @@
 	;;
 	ld4 out4=[r14]           // R15 == edi
 	movl r16=ia32_syscall_table
-	;; 
+	;;
 (p6)    shladd r16=r8,3,r16     // Force ni_syscall if not valid syscall number
 	ld8 r2=[r2]		// r2 = current->ptrace
-	;; 
+	;;
 	ld8 r16=[r16]
 	tbit.z p8,p0=r2,PT_TRACESYS_BIT	// (current->ptrace & PT_TRACESYS) == 0?
 	;;
@@ -857,7 +893,7 @@
 	;;
 	br.call.sptk.many rp=ia32_trace_syscall	// rp will be overwritten (ignored)
 
-non_ia32_syscall:       
+non_ia32_syscall:
 	alloc r15=ar.pfs,0,0,2,0
 	mov out0=r14                            // interrupt #
 	add out1=16,sp                          // pointer to pt_regs
@@ -867,16 +903,17 @@
 	;;
 	mov rp=r15
 	br.ret.sptk.many rp
-	;;
+END(dispatch_to_ia32_handler)
 
 #endif /* CONFIG_IA32_SUPPORT */
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x4400 Entry 17 (size 64 bundles) Reserved
+	DBG_FAULT(17)
 	FAULT(17)
 
-non_syscall:
+ENTRY(non_syscall)
 	SAVE_MIN_WITH_COVER
 
 	// There is no particular reason for this code to be here, other than that
@@ -884,49 +921,45 @@
 	// fault ever gets "unreserved", simply moved the following code to a more
 	// suitable spot...
 
-	mov r8=cr.iim			// get break immediate (must be done while psr.ic is off)
+	alloc r14=ar.pfs,0,0,2,0
+	mov out0=cr.iim
+	add out1=16,sp
 	adds r3=8,r2			// set up second base pointer for SAVE_REST
 
-	// turn interrupt collection back on:
-	ssm psr.ic
+	ssm psr.ic | PSR_DEFAULT_BITS
 	;;
 	srlz.i				// guarantee that interrupt collection is enabled
 	;;
 (p15)	ssm psr.i			// restore psr.i
 	movl r15=ia64_leave_kernel
 	;;
-	alloc r14=ar.pfs,0,0,2,0
-	mov out0=r8			// break number
-	add out1=16,sp			// pointer to pt_regs
-	;;
 	SAVE_REST
 	mov rp=r15
 	;;
 	br.call.sptk.many b6=ia64_bad_break	// avoid WAW on CFM and ignore return addr
-	;;
+END(non_syscall)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x4800 Entry 18 (size 64 bundles) Reserved
+	DBG_FAULT(18)
 	FAULT(18)
 
-	// There is no particular reason for this code to be here, other than that
-	// there happens to be space here that would go unused otherwise.  If this
-	// fault ever gets "unreserved", simply moved the following code to a more
-	// suitable spot...
+	/*
+	 * There is no particular reason for this code to be here, other than that
+	 * there happens to be space here that would go unused otherwise.  If this
+	 * fault ever gets "unreserved", simply moved the following code to a more
+	 * suitable spot...
+	 */
 
-dispatch_unaligned_handler:
+ENTRY(dispatch_unaligned_handler)
 	SAVE_MIN_WITH_COVER
 	;;
-	//
-	// we can't have the alloc while psr.ic is cleared because 
-	// we might get a mandatory RSE (when you reach the end of the 
-	// rotating partition when doing the alloc) spill which could cause 
-	// a page fault on the kernel virtual address and the handler 
-	// wouldn't get the state to recover.
-	//
-	mov r15=cr.ifa
-	ssm psr.ic
+	alloc r14=ar.pfs,0,0,2,0		// now it's safe (must be first in insn group!)
+	mov out0=cr.ifa
+	adds out1=16,sp
+
+	ssm psr.ic | PSR_DEFAULT_BITS
 	;;
 	srlz.i					// guarantee that interrupt collection is enabled
 	;;
@@ -934,66 +967,53 @@
 	adds r3=8,r2				// set up second base pointer
 	;;
 	SAVE_REST
-	;;
-	alloc r14=ar.pfs,0,0,2,0		// now it's safe (must be first in insn group!)
-	;;					// avoid WAW on r14
 	movl r14=ia64_leave_kernel
-	mov out0=r15				// out0 = faulting address
-	adds out1=16,sp				// out1 = pointer to pt_regs
 	;;
 	mov rp=r14
 	br.sptk.many ia64_prepare_handle_unaligned
-	;;
+END(dispatch_unaligned_handler)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x4c00 Entry 19 (size 64 bundles) Reserved
+	DBG_FAULT(19)
 	FAULT(19)
 
-	// There is no particular reason for this code to be here, other than that
-	// there happens to be space here that would go unused otherwise.  If this
-	// fault ever gets "unreserved", simply moved the following code to a more
-	// suitable spot...
+	/*
+	 * There is no particular reason for this code to be here, other than that
+	 * there happens to be space here that would go unused otherwise.  If this
+	 * fault ever gets "unreserved", simply moved the following code to a more
+	 * suitable spot...
+	 */
 
-dispatch_to_fault_handler:
-	//
-	// Input:
-	//	psr.ic:	off
-	//	r19:	fault vector number (e.g., 24 for General Exception)
-	//	r31:	contains saved predicates (pr)
-	//
+ENTRY(dispatch_to_fault_handler)
+	/*
+	 * Input:
+	 *	psr.ic:	off
+	 *	r19:	fault vector number (e.g., 24 for General Exception)
+	 *	r31:	contains saved predicates (pr)
+	 */
 	SAVE_MIN_WITH_COVER_R19
-	//
-	// Copy control registers to temporary registers, then turn on psr bits,
-	// then copy the temporary regs to the output regs.  We have to do this
-	// because the "alloc" can cause a mandatory store which could lead to
-	// an "Alt DTLB" fault which we can handle only if psr.ic is on.
-	//
-	mov r8=cr.isr
-	mov r9=cr.ifa
-	mov r10=cr.iim
-	mov r11=cr.itir
+	alloc r14=ar.pfs,0,0,5,0
+	mov out0=r15
+	mov out1=cr.isr
+	mov out2=cr.ifa
+	mov out3=cr.iim
+	mov out4=cr.itir
 	;;
-	ssm psr.ic
+	ssm psr.ic | PSR_DEFAULT_BITS
 	;;
 	srlz.i					// guarantee that interrupt collection is enabled
 	;;
 (p15)	ssm psr.i				// restore psr.i
 	adds r3=8,r2				// set up second base pointer for SAVE_REST
 	;;
-	alloc r14=ar.pfs,0,0,5,0		// must be first in insn group
-	mov out0=r15
-	mov out1=r8
-	mov out2=r9
-	mov out3=r10
-	mov out4=r11
-	;;
 	SAVE_REST
 	movl r14=ia64_leave_kernel
 	;;
 	mov rp=r14
 	br.call.sptk.many b6=ia64_fault
-	;;
+END(dispatch_to_fault_handler)
 
 //
 // --- End of long entries, Beginning of short entries
@@ -1002,55 +1022,67 @@
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
+ENTRY(page_not_present)
+	DBG_FAULT(20)
 	mov r16=cr.ifa
 	rsm psr.dt
-	// The Linux page fault handler doesn't expect non-present pages to be in
-	// the TLB.  Flush the existing entry now, so we meet that expectation.
-	mov r17=_PAGE_SIZE_4K<<2
+	/*
+	 * The Linux page fault handler doesn't expect non-present pages to be in
+	 * the TLB.  Flush the existing entry now, so we meet that expectation.
+	 */
+	mov r17=PAGE_SHIFT<<2
 	;;
 	ptc.l r16,r17
 	;;
 	mov r31=pr
 	srlz.d
 	br.sptk.many page_fault
-	;;
+END(page_not_present)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
+ENTRY(key_permission)
+	DBG_FAULT(21)
 	mov r16=cr.ifa
 	rsm psr.dt
 	mov r31=pr
 	;;
 	srlz.d
 	br.sptk.many page_fault
-	;;
+END(key_permission)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
+ENTRY(iaccess_rights)
+	DBG_FAULT(22)
 	mov r16=cr.ifa
 	rsm psr.dt
 	mov r31=pr
 	;;
 	srlz.d
 	br.sptk.many page_fault
-	;;
+END(iaccess_rights)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
+ENTRY(daccess_rights)
+	DBG_FAULT(23)
 	mov r16=cr.ifa
 	rsm psr.dt
 	mov r31=pr
 	;;
 	srlz.d
 	br.sptk.many page_fault
-	;;
+END(daccess_rights)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
+ENTRY(general_exception)
+	DBG_FAULT(24)
 	mov r16=cr.isr
 	mov r31=pr
 	;;
@@ -1059,39 +1091,44 @@
 	;;
 	mov r19=24		// fault number
 	br.sptk.many dispatch_to_fault_handler
-	;;
+END(general_exception)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
+ENTRY(disabled_fp_reg)
+	DBG_FAULT(25)
 	rsm psr.dfh		// ensure we can access fph
 	;;
 	srlz.d
 	mov r31=pr
 	mov r19=25
 	br.sptk.many dispatch_to_fault_handler
-	;;
+END(disabled_fp_reg)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
+ENTRY(nat_consumption)
+	DBG_FAULT(26)
 	FAULT(26)
+END(nat_consumption)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5700 Entry 27 (size 16 bundles) Speculation (40)
-	//
-	// A [f]chk.[as] instruction needs to take the branch to
-	// the recovery code but this part of the architecture is
-	// not implemented in hardware on some CPUs, such as Itanium.
-	// Thus, in general we need to emulate the behavior.
-	// IIM contains the relative target (not yet sign extended).
-	// So after sign extending it we simply add it to IIP.
-	// We also need to reset the EI field of the IPSR to zero,
-	// i.e., the slot to restart into.
-	//
-	// cr.imm contains zero_ext(imm21)
-	//
+ENTRY(speculation_vector)
+	DBG_FAULT(27)
+	/*
+	 * A [f]chk.[as] instruction needs to take the branch to the recovery code but
+	 * this part of the architecture is not implemented in hardware on some CPUs, such
+	 * as Itanium.  Thus, in general we need to emulate the behavior.  IIM contains
+	 * the relative target (not yet sign extended).  So after sign extending it we
+	 * simply add it to IIP.  We also need to reset the EI field of the IPSR to zero,
+	 * i.e., the slot to restart into.
+	 *
+	 * cr.imm contains zero_ext(imm21)
+	 */
 	mov r18=cr.iim
 	;;
 	mov r17=cr.iip
@@ -1112,105 +1149,130 @@
 	;;
 
 	rfi				// and go back
-	;;
+END(speculation_vector)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5800 Entry 28 (size 16 bundles) Reserved
+	DBG_FAULT(28)
 	FAULT(28)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
+ENTRY(debug_vector)
+	DBG_FAULT(29)
 	FAULT(29)
+END(debug_vector)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
+ENTRY(unaligned_access)
+	DBG_FAULT(30)
 	mov r16=cr.ipsr
 	mov r31=pr		// prepare to save predicates
-	;;									
-	br.sptk.many dispatch_unaligned_handler
 	;;
+	br.sptk.many dispatch_unaligned_handler
+END(unaligned_access)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
+	DBG_FAULT(31)
 	FAULT(31)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
+	DBG_FAULT(32)
 	FAULT(32)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
+	DBG_FAULT(33)
 	FAULT(33)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Tranfer Trap (66)
+	DBG_FAULT(34)
 	FAULT(34)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
+	DBG_FAULT(35)
 	FAULT(35)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
+	DBG_FAULT(36)
 	FAULT(36)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6100 Entry 37 (size 16 bundles) Reserved
+	DBG_FAULT(37)
 	FAULT(37)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6200 Entry 38 (size 16 bundles) Reserved
+	DBG_FAULT(38)
 	FAULT(38)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6300 Entry 39 (size 16 bundles) Reserved
+	DBG_FAULT(39)
 	FAULT(39)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6400 Entry 40 (size 16 bundles) Reserved
+	DBG_FAULT(40)
 	FAULT(40)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6500 Entry 41 (size 16 bundles) Reserved
+	DBG_FAULT(41)
 	FAULT(41)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6600 Entry 42 (size 16 bundles) Reserved
+	DBG_FAULT(42)
 	FAULT(42)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6700 Entry 43 (size 16 bundles) Reserved
+	DBG_FAULT(43)
 	FAULT(43)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6800 Entry 44 (size 16 bundles) Reserved
+	DBG_FAULT(44)
 	FAULT(44)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
+ENTRY(ia32_exception)
+	DBG_FAULT(45)
 	FAULT(45)
+END(ia32_exception)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept  (30,31,59,70,71)
+ENTRY(ia32_intercept)
+	DBG_FAULT(46)
 #ifdef	CONFIG_IA32_SUPPORT
 	mov r31=pr
 	mov r16=cr.isr
@@ -1219,129 +1281,152 @@
 	mov r18=ar.eflag
 	mov r19=cr.iim		// old eflag value
 	;;
-	cmp.ne p2,p0=2,r17
-(p2)	br.cond.spnt 1f		// not a system flag fault
+	cmp.ne p6,p0=2,r17
+(p6)	br.cond.spnt 1f		// not a system flag fault
 	xor r16=r18,r19
 	;;
 	extr.u r17=r16,18,1	// get the eflags.ac bit
 	;;
-	cmp.eq p2,p0=0,r17
-(p2)	br.cond.spnt 1f		// eflags.ac bit didn't change
+	cmp.eq p6,p0=0,r17
+(p6)	br.cond.spnt 1f		// eflags.ac bit didn't change
 	;;
 	mov pr=r31,-1		// restore predicate registers
 	rfi
-	;;
+
 1:
 #endif	// CONFIG_IA32_SUPPORT
 	FAULT(46)
+END(ia32_intercept)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt  (74)
+ENTRY(ia32_interrupt)
+	DBG_FAULT(47)
 #ifdef CONFIG_IA32_SUPPORT
 	mov r31=pr
 	br.sptk.many dispatch_to_ia32_handler
-	;;
 #else
 	FAULT(47)
 #endif
+END(ia32_interrupt)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6c00 Entry 48 (size 16 bundles) Reserved
+	DBG_FAULT(48)
 	FAULT(48)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6d00 Entry 49 (size 16 bundles) Reserved
+	DBG_FAULT(49)
 	FAULT(49)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6e00 Entry 50 (size 16 bundles) Reserved
+	DBG_FAULT(50)
 	FAULT(50)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x6f00 Entry 51 (size 16 bundles) Reserved
+	DBG_FAULT(51)
 	FAULT(51)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7000 Entry 52 (size 16 bundles) Reserved
+	DBG_FAULT(52)
 	FAULT(52)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7100 Entry 53 (size 16 bundles) Reserved
+	DBG_FAULT(53)
 	FAULT(53)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7200 Entry 54 (size 16 bundles) Reserved
+	DBG_FAULT(54)
 	FAULT(54)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7300 Entry 55 (size 16 bundles) Reserved
+	DBG_FAULT(55)
 	FAULT(55)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7400 Entry 56 (size 16 bundles) Reserved
+	DBG_FAULT(56)
 	FAULT(56)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7500 Entry 57 (size 16 bundles) Reserved
+	DBG_FAULT(57)
 	FAULT(57)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7600 Entry 58 (size 16 bundles) Reserved
+	DBG_FAULT(58)
 	FAULT(58)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7700 Entry 59 (size 16 bundles) Reserved
+	DBG_FAULT(59)
 	FAULT(59)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7800 Entry 60 (size 16 bundles) Reserved
+	DBG_FAULT(60)
 	FAULT(60)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7900 Entry 61 (size 16 bundles) Reserved
+	DBG_FAULT(61)
 	FAULT(61)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7a00 Entry 62 (size 16 bundles) Reserved
+	DBG_FAULT(62)
 	FAULT(62)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7b00 Entry 63 (size 16 bundles) Reserved
+	DBG_FAULT(63)
 	FAULT(63)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7c00 Entry 64 (size 16 bundles) Reserved
+	DBG_FAULT(64)
 	FAULT(64)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7d00 Entry 65 (size 16 bundles) Reserved
+	DBG_FAULT(65)
 	FAULT(65)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7e00 Entry 66 (size 16 bundles) Reserved
+	DBG_FAULT(66)
 	FAULT(66)
 
 	.align 256
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x7f00 Entry 67 (size 16 bundles) Reserved
+	DBG_FAULT(67)
 	FAULT(67)
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/mca.c linux/arch/ia64/kernel/mca.c
--- v2.4.3/linux/arch/ia64/kernel/mca.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/kernel/mca.c	Thu Apr 12 12:16:35 2001
@@ -1,16 +1,16 @@
 /*
- * File: 	mca.c
- * Purpose: 	Generic MCA handling layer
+ * File:	mca.c
+ * Purpose:	Generic MCA handling layer
  *
  * Updated for latest kernel
  * Copyright (C) 2000 Intel
  * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com)
- *  
+ *
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
  *
- * 00/03/29 C. Fleckenstein  Fixed PAL/SAL update issues, began MCA bug fixes, logging issues, 
- *                           added min save state dump, added INIT handler. 
+ * 00/03/29 C. Fleckenstein  Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
+ *                           added min save state dump, added INIT handler.
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -28,7 +28,7 @@
 
 #include <asm/irq.h>
 
- 
+
 typedef struct ia64_fptr {
 	unsigned long fp;
 	unsigned long gp;
@@ -43,8 +43,8 @@
 u64				ia64_mca_bspstore[1024];
 u64				ia64_init_stack[INIT_TASK_SIZE] __attribute__((aligned(16)));
 
-static void			ia64_mca_cmc_vector_setup(int 		enable, 
-							  int_vector_t 	cmc_vector);
+static void			ia64_mca_cmc_vector_setup(int		enable,
+							  int_vector_t	cmc_vector);
 static void			ia64_mca_wakeup_ipi_wait(void);
 static void			ia64_mca_wakeup(int cpu);
 static void			ia64_mca_wakeup_all(void);
@@ -77,7 +77,7 @@
  * console, then we would call the appropriate debug hooks here.
  */
 void
-init_handler_platform (struct pt_regs *regs) 
+init_handler_platform (struct pt_regs *regs)
 {
 	/* if a kernel debugger is available call it here else just dump the registers */
 	show_regs(regs);		/* dump the state info */
@@ -87,7 +87,7 @@
 log_print_platform ( void *cur_buff_ptr, prfunc_t prfunc)
 {
 }
-	
+
 void
 ia64_mca_init_platform (void)
 {
@@ -131,7 +131,7 @@
 				tpmss_ptr++;  /* skip to next entry */
 				continue;
 			}
-		} 
+		}
 
 		printk("%5s=0x%16.16lx ",min_state_labels[i],*tpmss_ptr++);
 
@@ -142,7 +142,7 @@
 	/* hang city for now, until we include debugger or copy to ptregs to show: */
 	while (1);
 }
- 
+
 /*
  * ia64_mca_cmc_vector_setup
  *	Setup the correctable machine check vector register in the processor
@@ -154,14 +154,14 @@
  *	None
  */
 static void
-ia64_mca_cmc_vector_setup(int 		enable, 
-			  int_vector_t 	cmc_vector)
+ia64_mca_cmc_vector_setup(int		enable,
+			  int_vector_t	cmc_vector)
 {
 	cmcv_reg_t	cmcv;
 
-	cmcv.cmcv_regval 	= 0;
-	cmcv.cmcv_mask  	= enable;
-	cmcv.cmcv_vector 	= cmc_vector;
+	cmcv.cmcv_regval	= 0;
+	cmcv.cmcv_mask	= enable;
+	cmcv.cmcv_vector	= cmc_vector;
 	ia64_set_cmcv(cmcv.cmcv_regval);
 }
 
@@ -223,25 +223,27 @@
 	for(i = 0 ; i < IA64_MAXCPUS; i++)
 		ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
 
-	/* NOTE : The actual irqs for the rendez, wakeup and 
+	/* NOTE : The actual irqs for the rendez, wakeup and
 	 * cmc interrupts are requested in the platform-specific
 	 * mca initialization code.
 	 */
-	/* 
+	/*
 	 * Register the rendezvous spinloop and wakeup mechanism with SAL
 	 */
 
 	/* Register the rendezvous interrupt vector with SAL */
 	if (ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
 				   SAL_MC_PARAM_MECHANISM_INT,
-				   IA64_MCA_RENDEZ_INT_VECTOR,
-				   IA64_MCA_RENDEZ_TIMEOUT))
+				   IA64_MCA_RENDEZ_VECTOR,
+				   IA64_MCA_RENDEZ_TIMEOUT,
+				   0))
 		return;
 
 	/* Register the wakeup interrupt vector with SAL */
 	if (ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
 				   SAL_MC_PARAM_MECHANISM_INT,
-				   IA64_MCA_WAKEUP_INT_VECTOR,
+				   IA64_MCA_WAKEUP_VECTOR,
+				   0,
 				   0))
 		return;
 
@@ -249,17 +251,16 @@
 	/*
 	 * Setup the correctable machine check vector
 	 */
-	ia64_mca_cmc_vector_setup(IA64_CMC_INT_ENABLE, 
-				  IA64_MCA_CMC_INT_VECTOR);
+	ia64_mca_cmc_vector_setup(IA64_CMC_INT_ENABLE, IA64_CMC_VECTOR);
 
 	IA64_MCA_DEBUG("ia64_mca_init : correctable mca vector setup done\n");
 
-	ia64_mc_info.imi_mca_handler 		= __pa(ia64_os_mca_dispatch);
+	ia64_mc_info.imi_mca_handler		= __pa(ia64_os_mca_dispatch);
 	/*
 	 * XXX - disable SAL checksum by setting size to 0; should be
 	 *	__pa(ia64_os_mca_dispatch_end) - __pa(ia64_os_mca_dispatch);
 	 */
-	ia64_mc_info.imi_mca_handler_size	= 0; 
+	ia64_mc_info.imi_mca_handler_size	= 0;
 	/* Register the os mca handler with SAL */
 	if (ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
 				 ia64_mc_info.imi_mca_handler,
@@ -271,13 +272,13 @@
 
 	IA64_MCA_DEBUG("ia64_mca_init : registered os mca handler with SAL\n");
 
-	/* 
+	/*
 	 * XXX - disable SAL checksum by setting size to 0, should be
-	 * IA64_INIT_HANDLER_SIZE 
+	 * IA64_INIT_HANDLER_SIZE
 	 */
-	ia64_mc_info.imi_monarch_init_handler 		= __pa(mon_init_ptr->fp);
+	ia64_mc_info.imi_monarch_init_handler		= __pa(mon_init_ptr->fp);
 	ia64_mc_info.imi_monarch_init_handler_size	= 0;
-	ia64_mc_info.imi_slave_init_handler 		= __pa(slave_init_ptr->fp);
+	ia64_mc_info.imi_slave_init_handler		= __pa(slave_init_ptr->fp);
 	ia64_mc_info.imi_slave_init_handler_size	= 0;
 
 	IA64_MCA_DEBUG("ia64_mca_init : os init handler at %lx\n",ia64_mc_info.imi_monarch_init_handler);
@@ -296,7 +297,7 @@
 
 	IA64_MCA_DEBUG("ia64_mca_init : registered os init handler with SAL\n");
 
-	/* Initialize the areas set aside by the OS to buffer the 
+	/* Initialize the areas set aside by the OS to buffer the
 	 * platform/processor error states for MCA/INIT/CMC
 	 * handling.
 	 */
@@ -308,7 +309,7 @@
 	ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM);
 
 	ia64_mca_init_platform();
-	
+
 	IA64_MCA_DEBUG("ia64_mca_init : platform-specific mca handling setup done\n");
 
 #if defined(MCA_TEST)
@@ -321,9 +322,9 @@
 /*
  * ia64_mca_wakeup_ipi_wait
  *	Wait for the inter-cpu interrupt to be sent by the
- * 	monarch processor once it is done with handling the
+ *	monarch processor once it is done with handling the
  *	MCA.
- * Inputs 
+ * Inputs
  *	None
  * Outputs
  *	None
@@ -331,8 +332,8 @@
 void
 ia64_mca_wakeup_ipi_wait(void)
 {
-	int	irr_num = (IA64_MCA_WAKEUP_INT_VECTOR >> 6);
-	int	irr_bit = (IA64_MCA_WAKEUP_INT_VECTOR & 0x3f);
+	int	irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6);
+	int	irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f);
 	u64	irr = 0;
 
 	do {
@@ -356,7 +357,7 @@
 /*
  * ia64_mca_wakeup
  *	Send an inter-cpu interrupt to wake-up a particular cpu
- * 	and mark that cpu to be out of rendez.
+ *	and mark that cpu to be out of rendez.
  * Inputs
  *	cpuid
  * Outputs
@@ -365,9 +366,8 @@
 void
 ia64_mca_wakeup(int cpu)
 {
-	platform_send_ipi(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT, 0);
+	platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0);
 	ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
-	
 }
 /*
  * ia64_mca_wakeup_all
@@ -390,10 +390,10 @@
 }
 /*
  * ia64_mca_rendez_interrupt_handler
- *	This is handler used to put slave processors into spinloop 
+ *	This is handler used to put slave processors into spinloop
  *	while the monarch processor does the mca handling and later
  *	wake each slave up once the monarch is done.
- * Inputs 
+ * Inputs
  *	None
  * Outputs
  *	None
@@ -403,7 +403,7 @@
 {
 	int flags, cpu = 0;
 	/* Mask all interrupts */
-        save_and_cli(flags);
+	save_and_cli(flags);
 
 #ifdef CONFIG_SMP
 	cpu = cpu_logical_id(hard_smp_processor_id());
@@ -414,7 +414,7 @@
 	 */
 	ia64_sal_mc_rendez();
 
-	/* Wait for the wakeup IPI from the monarch 
+	/* Wait for the wakeup IPI from the monarch
 	 * This waiting is done by polling on the wakeup-interrupt
 	 * vector bit in the processor's IRRs
 	 */
@@ -430,30 +430,30 @@
 /*
  * ia64_mca_wakeup_int_handler
  *	The interrupt handler for processing the inter-cpu interrupt to the
- * 	slave cpu which was spinning in the rendez loop.
+ *	slave cpu which was spinning in the rendez loop.
  *	Since this spinning is done by turning off the interrupts and
- *	polling on the wakeup-interrupt bit in the IRR, there is 
+ *	polling on the wakeup-interrupt bit in the IRR, there is
  *	nothing useful to be done in the handler.
  *  Inputs
  *	wakeup_irq	(Wakeup-interrupt bit)
  *	arg		(Interrupt handler specific argument)
  *	ptregs		(Exception frame at the time of the interrupt)
  *  Outputs
- *	
+ *
  */
 void
 ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
 {
-	
+
 }
 
 /*
  * ia64_return_to_sal_check
  *	This is function called before going back from the OS_MCA handler
- * 	to the OS_MCA dispatch code which finally takes the control back
- * 	to the SAL.
+ *	to the OS_MCA dispatch code which finally takes the control back
+ *	to the SAL.
  *	The main purpose of this routine is to setup the OS_MCA to SAL
- *	return state which can be used by the OS_MCA dispatch code 
+ *	return state which can be used by the OS_MCA dispatch code
  *	just before going back to SAL.
  * Inputs
  *	None
@@ -467,16 +467,16 @@
 	/* Copy over some relevant stuff from the sal_to_os_mca_handoff
 	 * so that it can be used at the time of os_mca_to_sal_handoff
 	 */
-	ia64_os_to_sal_handoff_state.imots_sal_gp = 
+	ia64_os_to_sal_handoff_state.imots_sal_gp =
 		ia64_sal_to_os_handoff_state.imsto_sal_gp;
 
-	ia64_os_to_sal_handoff_state.imots_sal_check_ra = 
+	ia64_os_to_sal_handoff_state.imots_sal_check_ra =
 		ia64_sal_to_os_handoff_state.imsto_sal_check_ra;
 
 	/* For now ignore the MCA */
 	ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;
 }
-/* 
+/*
  * ia64_mca_ucmc_handler
  *	This is uncorrectable machine check handler called from OS_MCA
  *	dispatch code which is in turn called from SAL_CHECK().
@@ -503,7 +503,7 @@
 
 	ia64_log_print(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
 
-	/* 
+	/*
 	 * Do some error handling - Platform-specific mca handler is called at this point
 	 */
 
@@ -520,11 +520,11 @@
 	ia64_return_to_sal_check();
 }
 
-/* 
+/*
  * ia64_mca_cmc_int_handler
  *	This is correctable machine check interrupt handler.
  *	Right now the logs are extracted and displayed in a well-defined
- *	format. 
+ *	format.
  * Inputs
  *	None
  * Outputs
@@ -532,7 +532,7 @@
  */
 void
 ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
-{	
+{
 	/* Get the CMC processor log */
 	ia64_log_get(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
 	/* Get the CMC platform log */
@@ -543,8 +543,7 @@
 	cmci_handler_platform(cmc_irq, arg, ptregs);
 
 	/* Clear the CMC SAL logs now that they have been saved in the OS buffer */
-	ia64_sal_clear_state_info(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR);
-	ia64_sal_clear_state_info(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM);
+	ia64_sal_clear_state_info(SAL_INFO_TYPE_CMC);
 }
 
 /*
@@ -563,17 +562,17 @@
 static ia64_state_log_t	ia64_state_log[IA64_MAX_LOG_TYPES][IA64_MAX_LOG_SUBTYPES];
 
 #define IA64_LOG_LOCK_INIT(it, sit)	spin_lock_init(&ia64_state_log[it][sit].isl_lock)
-#define IA64_LOG_LOCK(it, sit)	 	spin_lock_irqsave(&ia64_state_log[it][sit].isl_lock, s)
-#define IA64_LOG_UNLOCK(it, sit) 	spin_unlock_irqrestore(&ia64_state_log[it][sit].isl_lock,\
+#define IA64_LOG_LOCK(it, sit)		spin_lock_irqsave(&ia64_state_log[it][sit].isl_lock, s)
+#define IA64_LOG_UNLOCK(it, sit)	spin_unlock_irqrestore(&ia64_state_log[it][sit].isl_lock,\
 							       s)
 #define IA64_LOG_NEXT_INDEX(it, sit)	ia64_state_log[it][sit].isl_index
-#define IA64_LOG_CURR_INDEX(it, sit) 	1 - ia64_state_log[it][sit].isl_index
+#define IA64_LOG_CURR_INDEX(it, sit)	1 - ia64_state_log[it][sit].isl_index
 #define IA64_LOG_INDEX_INC(it, sit)	\
 	ia64_state_log[it][sit].isl_index = 1 - ia64_state_log[it][sit].isl_index
 #define IA64_LOG_INDEX_DEC(it, sit)	\
 	ia64_state_log[it][sit].isl_index = 1 - ia64_state_log[it][sit].isl_index
-#define IA64_LOG_NEXT_BUFFER(it, sit) 	(void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_NEXT_INDEX(it,sit)]))
-#define IA64_LOG_CURR_BUFFER(it, sit) 	(void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_CURR_INDEX(it,sit)]))
+#define IA64_LOG_NEXT_BUFFER(it, sit)	(void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_NEXT_INDEX(it,sit)]))
+#define IA64_LOG_CURR_BUFFER(it, sit)	(void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_CURR_INDEX(it,sit)]))
 
 /*
  * C portion of the OS INIT handler
@@ -582,7 +581,7 @@
  *
  * Inputs: pointer to pt_regs where processor info was saved.
  *
- * Returns: 
+ * Returns:
  *   0 if SAL must warm boot the System
  *   1 if SAL must retrun to interrupted context using PAL_MC_RESUME
  *
@@ -601,49 +600,48 @@
 	/* Get the INIT platform log */
 	ia64_log_get(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk);
 
-#ifdef IA64_DUMP_ALL_PROC_INFO 
+#ifdef IA64_DUMP_ALL_PROC_INFO
 	ia64_log_print(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
-#endif 
+#endif
 
-	/* 
+	/*
 	 * get pointer to min state save area
 	 *
 	 */
 	plog_ptr=(ia64_psilog_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT,
 						       SAL_SUB_INFO_TYPE_PROCESSOR);
 	proc_ptr = &plog_ptr->devlog.proclog;
-	
+
 	ia64_process_min_state_save(&proc_ptr->slpi_min_state_area,regs);
 
 	init_handler_platform(regs);              /* call platform specific routines */
 
 	/* Clear the INIT SAL logs now that they have been saved in the OS buffer */
-	ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR);
-	ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM);
+	ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT);
 }
 
 /*
  * ia64_log_init
- * 	Reset the OS ia64 log buffer
- * Inputs 	:	info_type 	(SAL_INFO_TYPE_{MCA,INIT,CMC})
+ *	Reset the OS ia64 log buffer
+ * Inputs	:	info_type	(SAL_INFO_TYPE_{MCA,INIT,CMC})
  *			sub_info_type	(SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
- * Outputs	: 	None
+ * Outputs	:	None
  */
 void
 ia64_log_init(int sal_info_type, int sal_sub_info_type)
 {
 	IA64_LOG_LOCK_INIT(sal_info_type, sal_sub_info_type);
 	IA64_LOG_NEXT_INDEX(sal_info_type, sal_sub_info_type) = 0;
-	memset(IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type), 0, 
+	memset(IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type), 0,
 	       sizeof(ia64_psilog_t) * IA64_MAX_LOGS);
 }
 
-/* 
+/*
  * ia64_log_get
- * 	Get the current MCA log from SAL and copy it into the OS log buffer.
- * Inputs 	:	info_type 	(SAL_INFO_TYPE_{MCA,INIT,CMC})
+ *	Get the current MCA log from SAL and copy it into the OS log buffer.
+ * Inputs	:	info_type	(SAL_INFO_TYPE_{MCA,INIT,CMC})
  *			sub_info_type	(SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
- * Outputs	: 	None
+ * Outputs	:	None
  *
  */
 void
@@ -658,7 +656,7 @@
 	/* Get the process state information */
 	log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type);
 
-	if (!(total_len=ia64_sal_get_state_info(sal_info_type, sal_sub_info_type ,(u64 *)log_buffer)))
+	if (!(total_len=ia64_sal_get_state_info(sal_info_type,(u64 *)log_buffer)))
 		prfunc("ia64_mca_log_get : Getting processor log failed\n");
 
 	IA64_MCA_DEBUG("ia64_log_get: retrieved %d bytes of error information\n",total_len);
@@ -669,21 +667,21 @@
 
 }
 
-/* 
+/*
  * ia64_log_clear
- * 	Clear the current MCA log from SAL and dpending on the clear_os_buffer flags
+ *	Clear the current MCA log from SAL and dpending on the clear_os_buffer flags
  *	clear the OS log buffer also
- * Inputs 	:	info_type 	(SAL_INFO_TYPE_{MCA,INIT,CMC})
+ * Inputs	:	info_type	(SAL_INFO_TYPE_{MCA,INIT,CMC})
  *			sub_info_type	(SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
- *			clear_os_buffer 
+ *			clear_os_buffer
  *			prfunc		(print function)
- * Outputs	: 	None
+ * Outputs	:	None
  *
  */
 void
 ia64_log_clear(int sal_info_type, int sal_sub_info_type, int clear_os_buffer, prfunc_t prfunc)
 {
-	if (ia64_sal_clear_state_info(sal_info_type, sal_sub_info_type))
+	if (ia64_sal_clear_state_info(sal_info_type))
 		prfunc("ia64_mca_log_get : Clearing processor log failed\n");
 
 	if (clear_os_buffer) {
@@ -698,7 +696,7 @@
 		memset(log_buffer, 0, sizeof(ia64_psilog_t));
 
 		IA64_LOG_INDEX_DEC(sal_info_type, sal_sub_info_type);
-	
+
 		IA64_LOG_UNLOCK(sal_info_type, sal_sub_info_type);
 	}
 
@@ -708,19 +706,19 @@
  * ia64_log_processor_regs_print
  *	Print the contents of the saved processor register(s) in the format
  *		<reg_prefix>[<index>] <value>
- *		
- * Inputs	:	regs 		(Register save buffer)
- *			reg_num 	(# of registers)
+ *
+ * Inputs	:	regs		(Register save buffer)
+ *			reg_num	(# of registers)
  *			reg_class	(application/banked/control/bank1_general)
  *			reg_prefix	(ar/br/cr/b1_gr)
- * Outputs	: 	None
+ * Outputs	:	None
  *
  */
 void
-ia64_log_processor_regs_print(u64 	*regs, 
-			      int 	reg_num,
-			      char 	*reg_class,
-			      char 	*reg_prefix,
+ia64_log_processor_regs_print(u64	*regs,
+			      int	reg_num,
+			      char	*reg_class,
+			      char	*reg_prefix,
 			      prfunc_t	prfunc)
 {
 	int i;
@@ -756,14 +754,14 @@
  * ia64_log_cache_check_info_print
  *	Display the machine check information related to cache error(s).
  * Inputs	:	i		(Multiple errors are logged, i - index of logged error)
- *			info		(Machine check info logged by the PAL and later 
+ *			info		(Machine check info logged by the PAL and later
  *					 captured by the SAL)
  *			target_addr	(Address which caused the cache error)
- * Outputs	: 	None
+ * Outputs	:	None
  */
-void 
-ia64_log_cache_check_info_print(int 			i, 
-				pal_cache_check_info_t 	info,
+void
+ia64_log_cache_check_info_print(int			i,
+				pal_cache_check_info_t	info,
 				u64			target_addr,
 				prfunc_t		prfunc)
 {
@@ -794,13 +792,13 @@
  * ia64_log_tlb_check_info_print
  *	Display the machine check information related to tlb error(s).
  * Inputs	:	i		(Multiple errors are logged, i - index of logged error)
- *			info		(Machine check info logged by the PAL and later 
+ *			info		(Machine check info logged by the PAL and later
  *					 captured by the SAL)
- * Outputs	: 	None
+ * Outputs	:	None
  */
 
 void
-ia64_log_tlb_check_info_print(int 			i,
+ia64_log_tlb_check_info_print(int			i,
 			      pal_tlb_check_info_t	info,
 			      prfunc_t			prfunc)
 {
@@ -826,16 +824,16 @@
  * ia64_log_bus_check_info_print
  *	Display the machine check information related to bus error(s).
  * Inputs	:	i		(Multiple errors are logged, i - index of logged error)
- *			info		(Machine check info logged by the PAL and later 
+ *			info		(Machine check info logged by the PAL and later
  *					 captured by the SAL)
  *			req_addr	(Address of the requestor of the transaction)
  *			resp_addr	(Address of the responder of the transaction)
  *			target_addr	(Address where the data was to be delivered to  or
  *					 obtained from)
- * Outputs	: 	None
+ * Outputs	:	None
  */
 void
-ia64_log_bus_check_info_print(int 			i,
+ia64_log_bus_check_info_print(int			i,
 			      pal_bus_check_info_t	info,
 			      u64			req_addr,
 			      u64			resp_addr,
@@ -868,9 +866,9 @@
  * ia64_log_processor_info_print
  *	Display the processor-specific information logged by PAL as a part
  *	of MCA or INIT or CMC.
- * Inputs 	:	lh	(Pointer of the sal log header which specifies the format
+ * Inputs	:	lh	(Pointer of the sal log header which specifies the format
  *				 of SAL state info as specified by the SAL spec).
- * Outputs	: 	None
+ * Outputs	:	None
  */
 void
 ia64_log_processor_info_print(sal_log_header_t *lh, prfunc_t prfunc)
@@ -892,29 +890,29 @@
 	}
 
 	/* Print branch register contents if valid */
-	if (slpi->slpi_valid.slpi_br) 
+	if (slpi->slpi_valid.slpi_br)
 		ia64_log_processor_regs_print(slpi->slpi_br, 8, "Branch", "br", prfunc);
 
 	/* Print control register contents if valid */
-	if (slpi->slpi_valid.slpi_cr) 
+	if (slpi->slpi_valid.slpi_cr)
 		ia64_log_processor_regs_print(slpi->slpi_cr, 128, "Control", "cr", prfunc);
 
 	/* Print application register contents if valid */
-	if (slpi->slpi_valid.slpi_ar) 
+	if (slpi->slpi_valid.slpi_ar)
 		ia64_log_processor_regs_print(slpi->slpi_br, 128, "Application", "ar", prfunc);
 
 	/* Print region register contents if valid */
-	if (slpi->slpi_valid.slpi_rr) 
+	if (slpi->slpi_valid.slpi_rr)
 		ia64_log_processor_regs_print(slpi->slpi_rr, 8, "Region", "rr", prfunc);
 
 	/* Print floating-point register contents if valid */
-	if (slpi->slpi_valid.slpi_fr) 
-		ia64_log_processor_regs_print(slpi->slpi_fr, 128, "Floating-point", "fr", 
+	if (slpi->slpi_valid.slpi_fr)
+		ia64_log_processor_regs_print(slpi->slpi_fr, 128, "Floating-point", "fr",
 					      prfunc);
 
 	/* Print the cache check information if any*/
 	for (i = 0 ; i < MAX_CACHE_ERRORS; i++)
-		ia64_log_cache_check_info_print(i, 
+		ia64_log_cache_check_info_print(i,
 					slpi->slpi_cache_check_info[i].slpi_cache_check,
 					slpi->slpi_cache_check_info[i].slpi_target_address,
 						prfunc);
@@ -924,7 +922,7 @@
 
 	/* Print the bus check information if any*/
 	for (i = 0 ; i < MAX_BUS_ERRORS; i++)
-		ia64_log_bus_check_info_print(i, 
+		ia64_log_bus_check_info_print(i,
 					slpi->slpi_bus_check_info[i].slpi_bus_check,
 					slpi->slpi_bus_check_info[i].slpi_requestor_addr,
 					slpi->slpi_bus_check_info[i].slpi_responder_addr,
@@ -935,15 +933,15 @@
 
 /*
  * ia64_log_print
- * 	Display the contents of the OS error log information
- * Inputs 	:	info_type 	(SAL_INFO_TYPE_{MCA,INIT,CMC})
+ *	Display the contents of the OS error log information
+ * Inputs	:	info_type	(SAL_INFO_TYPE_{MCA,INIT,CMC})
  *			sub_info_type	(SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
- * Outputs	: 	None
+ * Outputs	:	None
  */
 void
 ia64_log_print(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc)
 {
-	char 	*info_type, *sub_info_type;
+	char	*info_type, *sub_info_type;
 
 	switch(sal_info_type) {
 	case SAL_INFO_TYPE_MCA:
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/mca_asm.S linux/arch/ia64/kernel/mca_asm.S
--- v2.4.3/linux/arch/ia64/kernel/mca_asm.S	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/kernel/mca_asm.S	Thu Apr  5 12:51:47 2001
@@ -1,4 +1,4 @@
-// 
+//
 // assembly portion of the IA64 MCA handling
 //
 // Mods by cfleck to integrate into kernel build
@@ -8,6 +8,7 @@
 //		   kstack, switch modes, jump to C INIT handler
 //
 #include <linux/config.h>
+
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/mca_asm.h>
@@ -17,13 +18,9 @@
  * When we get an machine check, the kernel stack pointer is no longer
  * valid, so we need to set a new stack pointer.
  */
-#define	MINSTATE_PHYS	/* Make sure stack access is physical for MINSTATE */ 
+#define	MINSTATE_PHYS	/* Make sure stack access is physical for MINSTATE */
 
 #include "minstate.h"
-	
-	.psr abi64
-	.psr lsb
-	.lsb
 
 /*
  *	SAL_TO_OS_MCA_HANDOFF_STATE
@@ -35,26 +32,26 @@
  *		6. GR12 = Return address to location within SAL_CHECK
  */
 #define SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(_tmp)		\
-        movl	_tmp=ia64_sal_to_os_handoff_state;;	\
-        st8	[_tmp]=r1,0x08;;			\
-        st8	[_tmp]=r8,0x08;;			\
-        st8	[_tmp]=r9,0x08;;			\
-        st8	[_tmp]=r10,0x08;;			\
-        st8	[_tmp]=r11,0x08;;			\
-        st8	[_tmp]=r12,0x08;;
+	movl	_tmp=ia64_sal_to_os_handoff_state;;	\
+	st8	[_tmp]=r1,0x08;;			\
+	st8	[_tmp]=r8,0x08;;			\
+	st8	[_tmp]=r9,0x08;;			\
+	st8	[_tmp]=r10,0x08;;			\
+	st8	[_tmp]=r11,0x08;;			\
+	st8	[_tmp]=r12,0x08;;
 
 /*
  *	OS_MCA_TO_SAL_HANDOFF_STATE
  *		1. GR8 = OS_MCA status
  *		2. GR9 = SAL GP (physical)
  *		3. GR22 = New min state save area pointer
- */	
+ */
 #define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp)	\
-        movl	_tmp=ia64_os_to_sal_handoff_state;;	\
+	movl	_tmp=ia64_os_to_sal_handoff_state;;	\
 	DATA_VA_TO_PA(_tmp);;				\
-        ld8	r8=[_tmp],0x08;;			\
-        ld8	r9=[_tmp],0x08;;			\
-        ld8	r22=[_tmp],0x08;;
+	ld8	r8=[_tmp],0x08;;			\
+	ld8	r9=[_tmp],0x08;;			\
+	ld8	r22=[_tmp],0x08;;
 
 /*
  *	BRANCH
@@ -65,9 +62,9 @@
  *		"ip" is the address of the instruction
  *	located at "from_label".
  *		"temp" is a scratch register like r2
- *		"adjust" needed for HP compiler. 
+ *		"adjust" needed for HP compiler.
  *	A screwup somewhere with constant arithmetic.
- */	
+ */
 #define BRANCH(to_label, temp, p, adjust)		\
 100:	(p)	mov		temp=ip;		\
 		;;					\
@@ -76,7 +73,7 @@
 	(p)	adds		temp=adjust,temp;	\
 		;;					\
 	(p)	mov		b1=temp	;		\
-	(p)	br		b1	
+	(p)	br		b1
 
 	.global ia64_os_mca_dispatch
 	.global ia64_os_mca_dispatch_end
@@ -88,11 +85,11 @@
 	.global	ia64_mca_stack
 	.global	ia64_mca_stackframe
 	.global	ia64_mca_bspstore
-	.global ia64_init_stack	
-			
+	.global ia64_init_stack
+
 	.text
 	.align 16
-	
+
 ia64_os_mca_dispatch:
 
 #if defined(MCA_TEST)
@@ -114,23 +111,23 @@
 	;;
 begin_os_mca_dump:
 	BRANCH(ia64_os_mca_proc_state_dump, r2, p0, 0x0)
-        ;;
+	;;
 ia64_os_mca_done_dump:
 
-	// Setup new stack frame for OS_MCA handling 
-        movl        r2=ia64_mca_bspstore		// local bspstore area location in r2
-        movl        r3=ia64_mca_stackframe		// save stack frame to memory in r3
-        rse_switch_context(r6,r3,r2);;                  // RSC management in this new context
-        movl        r12=ia64_mca_stack;;
+	// Setup new stack frame for OS_MCA handling
+	movl        r2=ia64_mca_bspstore		// local bspstore area location in r2
+	movl        r3=ia64_mca_stackframe		// save stack frame to memory in r3
+	rse_switch_context(r6,r3,r2);;                  // RSC management in this new context
+	movl        r12=ia64_mca_stack;;
 
 	// Enter virtual mode from physical mode
 	VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
 ia64_os_mca_virtual_begin:
 
 	// call our handler
-        movl		r2=ia64_mca_ucmc_handler;;
-        mov		b6=r2;;
-        br.call.sptk.few	b0=b6
+	movl		r2=ia64_mca_ucmc_handler;;
+	mov		b6=r2;;
+	br.call.sptk.few	b0=b6
 .ret0:
 	// Revert back to physical mode before going back to SAL
 	PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)
@@ -144,42 +141,36 @@
 #endif	/* #if defined(MCA_TEST) */
 
 	// restore the original stack frame here
-        movl    r2=ia64_mca_stackframe               // restore stack frame from memory at r2
+	movl    r2=ia64_mca_stackframe               // restore stack frame from memory at r2
 	;;
 	DATA_VA_TO_PA(r2)
-        movl    r4=IA64_PSR_MC
+	movl    r4=IA64_PSR_MC
 	;;
-        rse_return_context(r4,r3,r2)                 // switch from interrupt context for RSE
-	
+	rse_return_context(r4,r3,r2)                 // switch from interrupt context for RSE
+
 	// let us restore all the registers from our PSI structure
-        mov		r8=gp
+	mov		r8=gp
 	;;
 begin_os_mca_restore:
 	BRANCH(ia64_os_mca_proc_state_restore, r2, p0, 0x0)
-        ;;
+	;;
 
 ia64_os_mca_done_restore:
 	;;
-#ifdef SOFTSDV
-	VIRTUAL_MODE_ENTER(r2,r3, vmode_enter, r4)
-vmode_enter:	
-	br.ret.sptk.few		b0	
-#else
 	// branch back to SALE_CHECK
 	OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2)
-        ld8		r3=[r2];;              
-        mov		b0=r3                       // SAL_CHECK return address
-        br		b0
-        ;;
-#endif /* #ifdef SOFTSDV */
-ia64_os_mca_dispatch_end:	
+	ld8		r3=[r2];;
+	mov		b0=r3                       // SAL_CHECK return address
+	br		b0
+	;;
+ia64_os_mca_dispatch_end:
 //EndMain//////////////////////////////////////////////////////////////////////
 
 
 //++
 // Name:
 //      ia64_os_mca_proc_state_dump()
-// 
+//
 // Stub Description:
 //
 //       This stub dumps the processor state during MCHK to a data area
@@ -188,223 +179,223 @@
 
 ia64_os_mca_proc_state_dump:
 // Get and save GR0-31 from Proc. Min. State Save Area to SAL PSI
-        movl		r2=ia64_mca_proc_state_dump;;           // Os state dump area
+	movl		r2=ia64_mca_proc_state_dump;;           // Os state dump area
 
-// save ar.NaT 
-        mov		r5=ar.unat                  // ar.unat
+// save ar.NaT
+	mov		r5=ar.unat                  // ar.unat
 
 // save banked GRs 16-31 along with NaT bits
-        bsw.1;;
-        st8.spill	[r2]=r16,8;;
-        st8.spill	[r2]=r17,8;;
-        st8.spill	[r2]=r18,8;;
-        st8.spill	[r2]=r19,8;;
-        st8.spill	[r2]=r20,8;;
-        st8.spill	[r2]=r21,8;;
-        st8.spill	[r2]=r22,8;;
-        st8.spill	[r2]=r23,8;;
-        st8.spill	[r2]=r24,8;;
-        st8.spill	[r2]=r25,8;;
-        st8.spill	[r2]=r26,8;;
-        st8.spill	[r2]=r27,8;;
-        st8.spill	[r2]=r28,8;;
-        st8.spill	[r2]=r29,8;;
-        st8.spill	[r2]=r30,8;;
-        st8.spill	[r2]=r31,8;;
-
-        mov		r4=ar.unat;;
-        st8		[r2]=r4,8                // save User NaT bits for r16-r31
-        mov		ar.unat=r5                  // restore original unat
-        bsw.0;;
+	bsw.1;;
+	st8.spill	[r2]=r16,8;;
+	st8.spill	[r2]=r17,8;;
+	st8.spill	[r2]=r18,8;;
+	st8.spill	[r2]=r19,8;;
+	st8.spill	[r2]=r20,8;;
+	st8.spill	[r2]=r21,8;;
+	st8.spill	[r2]=r22,8;;
+	st8.spill	[r2]=r23,8;;
+	st8.spill	[r2]=r24,8;;
+	st8.spill	[r2]=r25,8;;
+	st8.spill	[r2]=r26,8;;
+	st8.spill	[r2]=r27,8;;
+	st8.spill	[r2]=r28,8;;
+	st8.spill	[r2]=r29,8;;
+	st8.spill	[r2]=r30,8;;
+	st8.spill	[r2]=r31,8;;
+
+	mov		r4=ar.unat;;
+	st8		[r2]=r4,8                // save User NaT bits for r16-r31
+	mov		ar.unat=r5                  // restore original unat
+	bsw.0;;
 
 //save BRs
-        add		r4=8,r2                  // duplicate r2 in r4
-        add		r6=2*8,r2                // duplicate r2 in r4
+	add		r4=8,r2                  // duplicate r2 in r4
+	add		r6=2*8,r2                // duplicate r2 in r4
 
-        mov		r3=b0
-        mov		r5=b1
-        mov		r7=b2;;
-        st8		[r2]=r3,3*8
-        st8		[r4]=r5,3*8
-        st8		[r6]=r7,3*8;;  
-
-        mov		r3=b3
-        mov		r5=b4
-        mov		r7=b5;;
-        st8		[r2]=r3,3*8
-        st8		[r4]=r5,3*8
-        st8		[r6]=r7,3*8;;  
-
-        mov		r3=b6
-        mov		r5=b7;;
-        st8		[r2]=r3,2*8
-        st8		[r4]=r5,2*8;;
+	mov		r3=b0
+	mov		r5=b1
+	mov		r7=b2;;
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
+
+	mov		r3=b3
+	mov		r5=b4
+	mov		r7=b5;;
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
+
+	mov		r3=b6
+	mov		r5=b7;;
+	st8		[r2]=r3,2*8
+	st8		[r4]=r5,2*8;;
 
 cSaveCRs:
 // save CRs
-        add		r4=8,r2                  // duplicate r2 in r4
-        add		r6=2*8,r2                // duplicate r2 in r4
+	add		r4=8,r2                  // duplicate r2 in r4
+	add		r6=2*8,r2                // duplicate r2 in r4
 
-        mov		r3=cr0                      // cr.dcr
-        mov		r5=cr1                      // cr.itm
-        mov		r7=cr2;;                    // cr.iva
-
-        st8		[r2]=r3,8*8
-        st8		[r4]=r5,3*8
-        st8		[r6]=r7,3*8;;            // 48 byte rements
+	mov		r3=cr0                      // cr.dcr
+	mov		r5=cr1                      // cr.itm
+	mov		r7=cr2;;                    // cr.iva
+
+	st8		[r2]=r3,8*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;            // 48 byte rements
 
-        mov		r3=cr8;;                    // cr.pta
-        st8		[r2]=r3,8*8;;            // 64 byte rements
+	mov		r3=cr8;;                    // cr.pta
+	st8		[r2]=r3,8*8;;            // 64 byte rements
 
 // if PSR.ic=0, reading interruption registers causes an illegal operation fault
-        mov		r3=psr;;
-        tbit.nz.unc	p2,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
-(p2)    st8		[r2]=r0,9*8+160             // increment by 168 byte inc.
-begin_skip_intr_regs:	
-	BRANCH(SkipIntrRegs,  r9, p2, 0x0)
-	;; 
-        add		r4=8,r2                  // duplicate r2 in r4
-        add		r6=2*8,r2                // duplicate r2 in r6
-        
-        mov		r3=cr16                     // cr.ipsr
-        mov		r5=cr17                     // cr.isr
-        mov		r7=r0;;                     // cr.ida => cr18
-        st8		[r2]=r3,3*8
-        st8		[r4]=r5,3*8
-        st8		[r6]=r7,3*8;;                                      
-
-        mov		r3=cr19                     // cr.iip
-        mov		r5=cr20                     // cr.idtr
-        mov		r7=cr21;;                   // cr.iitr
-        st8		[r2]=r3,3*8
-        st8		[r4]=r5,3*8
-        st8		[r6]=r7,3*8;;                                      
-
-        mov		r3=cr22                     // cr.iipa
-        mov		r5=cr23                     // cr.ifs
-        mov		r7=cr24;;                   // cr.iim
-        st8		[r2]=r3,3*8
-        st8		[r4]=r5,3*8
-        st8		[r6]=r7,3*8;;    
-                                          
-        mov		r3=cr25;;                   // cr.iha
-        st8		[r2]=r3,160;;               // 160 byte rement
+	mov		r3=psr;;
+	tbit.nz.unc	p6,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
+(p6)    st8		[r2]=r0,9*8+160             // increment by 168 byte inc.
+begin_skip_intr_regs:
+	BRANCH(SkipIntrRegs,  r9, p6, 0x0)
+	;;
+	add		r4=8,r2                  // duplicate r2 in r4
+	add		r6=2*8,r2                // duplicate r2 in r6
+
+	mov		r3=cr16                     // cr.ipsr
+	mov		r5=cr17                     // cr.isr
+	mov		r7=r0;;                     // cr.ida => cr18
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
+
+	mov		r3=cr19                     // cr.iip
+	mov		r5=cr20                     // cr.idtr
+	mov		r7=cr21;;                   // cr.iitr
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
+
+	mov		r3=cr22                     // cr.iipa
+	mov		r5=cr23                     // cr.ifs
+	mov		r7=cr24;;                   // cr.iim
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
+
+	mov		r3=cr25;;                   // cr.iha
+	st8		[r2]=r3,160;;               // 160 byte rement
 
 SkipIntrRegs:
-        st8		[r2]=r0,168                 // another 168 byte .
+	st8		[r2]=r0,168                 // another 168 byte .
 
-        mov		r3=cr66;;                   // cr.lid
-        st8		[r2]=r3,40                  // 40 byte rement
+	mov		r3=cr66;;                   // cr.lid
+	st8		[r2]=r3,40                  // 40 byte rement
 
-        mov		r3=cr71;;                   // cr.ivr
-        st8		[r2]=r3,8
+	mov		r3=cr71;;                   // cr.ivr
+	st8		[r2]=r3,8
 
-        mov		r3=cr72;;                   // cr.tpr
-        st8		[r2]=r3,24                  // 24 byte increment
-    
-        mov		r3=r0;;                     // cr.eoi => cr75
-        st8		[r2]=r3,168                 // 168 byte inc.
-    
-        mov		r3=r0;;                     // cr.irr0 => cr96
-        st8		[r2]=r3,16               // 16 byte inc.
+	mov		r3=cr72;;                   // cr.tpr
+	st8		[r2]=r3,24                  // 24 byte increment
 
-        mov		r3=r0;;                     // cr.irr1 => cr98
-        st8		[r2]=r3,16               // 16 byte inc.
+	mov		r3=r0;;                     // cr.eoi => cr75
+	st8		[r2]=r3,168                 // 168 byte inc.
 
-        mov		r3=r0;;                     // cr.irr2 => cr100
-        st8		[r2]=r3,16               // 16 byte inc
+	mov		r3=r0;;                     // cr.irr0 => cr96
+	st8		[r2]=r3,16               // 16 byte inc.
 
-        mov		r3=r0;;                     // cr.irr3 => cr100
-        st8		[r2]=r3,16               // 16b inc.
+	mov		r3=r0;;                     // cr.irr1 => cr98
+	st8		[r2]=r3,16               // 16 byte inc.
 
-        mov		r3=r0;;                     // cr.itv => cr114
-        st8		[r2]=r3,16               // 16 byte inc.
+	mov		r3=r0;;                     // cr.irr2 => cr100
+	st8		[r2]=r3,16               // 16 byte inc
 
-        mov		r3=r0;;                     // cr.pmv => cr116
-        st8		[r2]=r3,8
+	mov		r3=r0;;                     // cr.irr3 => cr100
+	st8		[r2]=r3,16               // 16b inc.
 
-        mov		r3=r0;;                     // cr.lrr0 => cr117
-        st8		[r2]=r3,8
+	mov		r3=r0;;                     // cr.itv => cr114
+	st8		[r2]=r3,16               // 16 byte inc.
 
-        mov		r3=r0;;                     // cr.lrr1 => cr118
-        st8		[r2]=r3,8
+	mov		r3=r0;;                     // cr.pmv => cr116
+	st8		[r2]=r3,8
 
-        mov		r3=r0;;                     // cr.cmcv => cr119
-        st8		[r2]=r3,8*10;;
+	mov		r3=r0;;                     // cr.lrr0 => cr117
+	st8		[r2]=r3,8
+
+	mov		r3=r0;;                     // cr.lrr1 => cr118
+	st8		[r2]=r3,8
+
+	mov		r3=r0;;                     // cr.cmcv => cr119
+	st8		[r2]=r3,8*10;;
 
 cSaveARs:
 // save ARs
-        add		r4=8,r2                  // duplicate r2 in r4
-        add		r6=2*8,r2                // duplicate r2 in r6
+	add		r4=8,r2                  // duplicate r2 in r4
+	add		r6=2*8,r2                // duplicate r2 in r6
 
-        mov		r3=ar0                      // ar.kro
-        mov		r5=ar1                      // ar.kr1
-        mov		r7=ar2;;                    // ar.kr2
-        st8		[r2]=r3,3*8
-        st8		[r4]=r5,3*8
-        st8		[r6]=r7,3*8;;
-
-        mov		r3=ar3                      // ar.kr3                               
-        mov		r5=ar4                      // ar.kr4
-        mov		r7=ar5;;                    // ar.kr5
-        st8		[r2]=r3,3*8
-        st8		[r4]=r5,3*8
-        st8		[r6]=r7,3*8;;
-
-        mov		r3=ar6                      // ar.kr6
-        mov		r5=ar7                      // ar.kr7
-        mov		r7=r0;;                     // ar.kr8
-        st8		[r2]=r3,10*8
-        st8		[r4]=r5,10*8
-        st8		[r6]=r7,10*8;;           // rement by 72 bytes
+	mov		r3=ar0                      // ar.kro
+	mov		r5=ar1                      // ar.kr1
+	mov		r7=ar2;;                    // ar.kr2
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
+
+	mov		r3=ar3                      // ar.kr3
+	mov		r5=ar4                      // ar.kr4
+	mov		r7=ar5;;                    // ar.kr5
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
+
+	mov		r3=ar6                      // ar.kr6
+	mov		r5=ar7                      // ar.kr7
+	mov		r7=r0;;                     // ar.kr8
+	st8		[r2]=r3,10*8
+	st8		[r4]=r5,10*8
+	st8		[r6]=r7,10*8;;           // rement by 72 bytes
 
-        mov		r3=ar16                     // ar.rsc
+	mov		r3=ar16                     // ar.rsc
 	mov		ar16=r0			    // put RSE in enforced lazy mode
-        mov		r5=ar17                     // ar.bsp
+	mov		r5=ar17                     // ar.bsp
 	;;
-        mov		r7=ar18;;                   // ar.bspstore
-        st8		[r2]=r3,3*8
-        st8		[r4]=r5,3*8
-        st8		[r6]=r7,3*8;;
+	mov		r7=ar18;;                   // ar.bspstore
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
 
-        mov		r3=ar19;;                   // ar.rnat
-        st8		[r2]=r3,8*13             // increment by 13x8 bytes
+	mov		r3=ar19;;                   // ar.rnat
+	st8		[r2]=r3,8*13             // increment by 13x8 bytes
 
-        mov		r3=ar32;;                   // ar.ccv
-        st8		[r2]=r3,8*4
+	mov		r3=ar32;;                   // ar.ccv
+	st8		[r2]=r3,8*4
 
-        mov		r3=ar36;;                   // ar.unat
-        st8		[r2]=r3,8*4
+	mov		r3=ar36;;                   // ar.unat
+	st8		[r2]=r3,8*4
 
-        mov		r3=ar40;;                   // ar.fpsr
-        st8		[r2]=r3,8*4
+	mov		r3=ar40;;                   // ar.fpsr
+	st8		[r2]=r3,8*4
 
-        mov		r3=ar44;;                   // ar.itc
-        st8		[r2]=r3,160                 // 160
+	mov		r3=ar44;;                   // ar.itc
+	st8		[r2]=r3,160                 // 160
 
-        mov		r3=ar64;;                   // ar.pfs
-        st8		[r2]=r3,8
+	mov		r3=ar64;;                   // ar.pfs
+	st8		[r2]=r3,8
 
-        mov		r3=ar65;;                   // ar.lc
-        st8		[r2]=r3,8
+	mov		r3=ar65;;                   // ar.lc
+	st8		[r2]=r3,8
+
+	mov		r3=ar66;;                   // ar.ec
+	st8		[r2]=r3
+	add		r2=8*62,r2               //padding
 
-        mov		r3=ar66;;                   // ar.ec
-        st8		[r2]=r3
-        add		r2=8*62,r2               //padding
-    
 // save RRs
-        mov		ar.lc=0x08-1
-        movl		r4=0x00;;
+	mov		ar.lc=0x08-1
+	movl		r4=0x00;;
 
 cStRR:
-        mov		r3=rr[r4];;
-        st8		[r2]=r3,8
-        add		r4=1,r4
-        br.cloop.sptk.few	cStRR
-        ;;
+	mov		r3=rr[r4];;
+	st8		[r2]=r3,8
+	add		r4=1,r4
+	br.cloop.sptk.few	cStRR
+	;;
 end_os_mca_dump:
 	BRANCH(ia64_os_mca_done_dump, r2, p0, -0x10)
-        ;;
+	;;
 
 //EndStub//////////////////////////////////////////////////////////////////////
 
@@ -412,7 +403,7 @@
 //++
 // Name:
 //       ia64_os_mca_proc_state_restore()
-// 
+//
 // Stub Description:
 //
 //       This is a stub to restore the saved processor state during MCHK
@@ -421,225 +412,225 @@
 
 ia64_os_mca_proc_state_restore:
 
-// Restore bank1 GR16-31 
+// Restore bank1 GR16-31
 	movl		r2=ia64_mca_proc_state_dump	// Convert virtual address
 	;;						// of OS state dump area
 	DATA_VA_TO_PA(r2)				// to physical address
 	;;
 restore_GRs:                                    // restore bank-1 GRs 16-31
-        bsw.1;;
-        add		r3=16*8,r2;;                // to get to NaT of GR 16-31
-        ld8		r3=[r3];;
-        mov		ar.unat=r3;;                // first restore NaT
-
-        ld8.fill	r16=[r2],8;;
-        ld8.fill	r17=[r2],8;;
-        ld8.fill	r18=[r2],8;;
-        ld8.fill	r19=[r2],8;;
-        ld8.fill	r20=[r2],8;;
-        ld8.fill	r21=[r2],8;;
-        ld8.fill	r22=[r2],8;;
-        ld8.fill	r23=[r2],8;;
-        ld8.fill	r24=[r2],8;;
-        ld8.fill	r25=[r2],8;;
-        ld8.fill	r26=[r2],8;;
-        ld8.fill	r27=[r2],8;;
-        ld8.fill	r28=[r2],8;;
-        ld8.fill	r29=[r2],8;;
-        ld8.fill	r30=[r2],8;;
-        ld8.fill	r31=[r2],8;;
+	bsw.1;;
+	add		r3=16*8,r2;;                // to get to NaT of GR 16-31
+	ld8		r3=[r3];;
+	mov		ar.unat=r3;;                // first restore NaT
+
+	ld8.fill	r16=[r2],8;;
+	ld8.fill	r17=[r2],8;;
+	ld8.fill	r18=[r2],8;;
+	ld8.fill	r19=[r2],8;;
+	ld8.fill	r20=[r2],8;;
+	ld8.fill	r21=[r2],8;;
+	ld8.fill	r22=[r2],8;;
+	ld8.fill	r23=[r2],8;;
+	ld8.fill	r24=[r2],8;;
+	ld8.fill	r25=[r2],8;;
+	ld8.fill	r26=[r2],8;;
+	ld8.fill	r27=[r2],8;;
+	ld8.fill	r28=[r2],8;;
+	ld8.fill	r29=[r2],8;;
+	ld8.fill	r30=[r2],8;;
+	ld8.fill	r31=[r2],8;;
 
-        ld8		r3=[r2],8;;              // increment to skip NaT
-        bsw.0;;
+	ld8		r3=[r2],8;;              // increment to skip NaT
+	bsw.0;;
 
 restore_BRs:
-        add		r4=8,r2                  // duplicate r2 in r4
-        add		r6=2*8,r2;;              // duplicate r2 in r4
+	add		r4=8,r2                  // duplicate r2 in r4
+	add		r6=2*8,r2;;              // duplicate r2 in r4
 
-        ld8		r3=[r2],3*8
-        ld8		r5=[r4],3*8
-        ld8		r7=[r6],3*8;;  
-        mov		b0=r3
-        mov		b1=r5
-        mov		b2=r7;;
-
-        ld8		r3=[r2],3*8
-        ld8		r5=[r4],3*8
-        ld8		r7=[r6],3*8;;  
-        mov		b3=r3
-        mov		b4=r5
-        mov		b5=r7;;
-
-        ld8		r3=[r2],2*8
-        ld8		r5=[r4],2*8;;  
-        mov		b6=r3
-        mov		b7=r5;;
+	ld8		r3=[r2],3*8
+	ld8		r5=[r4],3*8
+	ld8		r7=[r6],3*8;;
+	mov		b0=r3
+	mov		b1=r5
+	mov		b2=r7;;
+
+	ld8		r3=[r2],3*8
+	ld8		r5=[r4],3*8
+	ld8		r7=[r6],3*8;;
+	mov		b3=r3
+	mov		b4=r5
+	mov		b5=r7;;
+
+	ld8		r3=[r2],2*8
+	ld8		r5=[r4],2*8;;
+	mov		b6=r3
+	mov		b7=r5;;
 
 restore_CRs:
-        add		r4=8,r2                  // duplicate r2 in r4
-        add		r6=2*8,r2;;              // duplicate r2 in r4
+	add		r4=8,r2                  // duplicate r2 in r4
+	add		r6=2*8,r2;;              // duplicate r2 in r4
 
-        ld8		r3=[r2],8*8
-        ld8		r5=[r4],3*8
-        ld8		r7=[r6],3*8;;            // 48 byte increments
-        mov		cr0=r3                      // cr.dcr
-        mov		cr1=r5                      // cr.itm
-        mov		cr2=r7;;                    // cr.iva
+	ld8		r3=[r2],8*8
+	ld8		r5=[r4],3*8
+	ld8		r7=[r6],3*8;;            // 48 byte increments
+	mov		cr0=r3                      // cr.dcr
+	mov		cr1=r5                      // cr.itm
+	mov		cr2=r7;;                    // cr.iva
 
-        ld8		r3=[r2],8*8;;            // 64 byte increments
+	ld8		r3=[r2],8*8;;            // 64 byte increments
 //      mov		cr8=r3                      // cr.pta
 
 
 // if PSR.ic=1, reading interruption registers causes an illegal operation fault
-        mov		r3=psr;;
-        tbit.nz.unc	p2,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
-(p2)    st8		[r2]=r0,9*8+160             // increment by 160 byte inc.
-
-begin_rskip_intr_regs:	
-	BRANCH(rSkipIntrRegs, r9, p2, 0x0)
-	;; 
-
-        add		r4=8,r2                  // duplicate r2 in r4
-        add		r6=2*8,r2;;              // duplicate r2 in r4
-
-        ld8		r3=[r2],3*8
-        ld8		r5=[r4],3*8
-        ld8		r7=[r6],3*8;;
-        mov		cr16=r3                     // cr.ipsr
-        mov		cr17=r5                     // cr.isr is read only
+	mov		r3=psr;;
+	tbit.nz.unc	p6,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
+(p6)    st8		[r2]=r0,9*8+160             // increment by 160 byte inc.
+
+begin_rskip_intr_regs:
+	BRANCH(rSkipIntrRegs, r9, p6, 0x0)
+	;;
+
+	add		r4=8,r2                  // duplicate r2 in r4
+	add		r6=2*8,r2;;              // duplicate r2 in r4
+
+	ld8		r3=[r2],3*8
+	ld8		r5=[r4],3*8
+	ld8		r7=[r6],3*8;;
+	mov		cr16=r3                     // cr.ipsr
+	mov		cr17=r5                     // cr.isr is read only
 //      mov		cr18=r7;;                   // cr.ida
 
-        ld8		r3=[r2],3*8
-        ld8		r5=[r4],3*8
-        ld8		r7=[r6],3*8;;
-        mov		cr19=r3                     // cr.iip
-        mov		cr20=r5                     // cr.idtr
-        mov		cr21=r7;;                   // cr.iitr
-
-        ld8		r3=[r2],3*8
-        ld8		r5=[r4],3*8
-        ld8		r7=[r6],3*8;;
-        mov		cr22=r3                     // cr.iipa
-        mov		cr23=r5                     // cr.ifs
-        mov		cr24=r7                     // cr.iim
+	ld8		r3=[r2],3*8
+	ld8		r5=[r4],3*8
+	ld8		r7=[r6],3*8;;
+	mov		cr19=r3                     // cr.iip
+	mov		cr20=r5                     // cr.idtr
+	mov		cr21=r7;;                   // cr.iitr
+
+	ld8		r3=[r2],3*8
+	ld8		r5=[r4],3*8
+	ld8		r7=[r6],3*8;;
+	mov		cr22=r3                     // cr.iipa
+	mov		cr23=r5                     // cr.ifs
+	mov		cr24=r7                     // cr.iim
 
-        ld8		r3=[r2],160;;               // 160 byte increment
-        mov		cr25=r3                     // cr.iha 
+	ld8		r3=[r2],160;;               // 160 byte increment
+	mov		cr25=r3                     // cr.iha
 
 rSkipIntrRegs:
-        ld8		r3=[r2],168;;               // another 168 byte inc.
+	ld8		r3=[r2],168;;               // another 168 byte inc.
 
-        ld8		r3=[r2],40;;                // 40 byte increment
-        mov		cr66=r3                     // cr.lid
+	ld8		r3=[r2],40;;                // 40 byte increment
+	mov		cr66=r3                     // cr.lid
 
-        ld8		r3=[r2],8;;
+	ld8		r3=[r2],8;;
 //      mov		cr71=r3                     // cr.ivr is read only
-        ld8		r3=[r2],24;;                // 24 byte increment
-        mov		cr72=r3                     // cr.tpr
-   
-        ld8		r3=[r2],168;;               // 168 byte inc.
+	ld8		r3=[r2],24;;                // 24 byte increment
+	mov		cr72=r3                     // cr.tpr
+
+	ld8		r3=[r2],168;;               // 168 byte inc.
 //      mov		cr75=r3                     // cr.eoi
-   
-        ld8		r3=[r2],16;;             // 16 byte inc.
+
+	ld8		r3=[r2],16;;             // 16 byte inc.
 //      mov		cr96=r3                     // cr.irr0 is read only
 
-        ld8		r3=[r2],16;;             // 16 byte inc.
+	ld8		r3=[r2],16;;             // 16 byte inc.
 //      mov		cr98=r3                     // cr.irr1 is read only
 
-        ld8		r3=[r2],16;;             // 16 byte inc
+	ld8		r3=[r2],16;;             // 16 byte inc
 //      mov		cr100=r3                    // cr.irr2 is read only
 
-        ld8		r3=[r2],16;;             // 16b inc.
+	ld8		r3=[r2],16;;             // 16b inc.
 //      mov		cr102=r3                    // cr.irr3 is read only
 
-        ld8		r3=[r2],16;;             // 16 byte inc.
+	ld8		r3=[r2],16;;             // 16 byte inc.
 //      mov		cr114=r3                    // cr.itv
 
-        ld8		r3=[r2],8;;
+	ld8		r3=[r2],8;;
 //      mov		cr116=r3                    // cr.pmv
-        ld8		r3=[r2],8;;
+	ld8		r3=[r2],8;;
 //      mov		cr117=r3                    // cr.lrr0
-        ld8		r3=[r2],8;;
+	ld8		r3=[r2],8;;
 //      mov		cr118=r3                    // cr.lrr1
-        ld8		r3=[r2],8*10;;
+	ld8		r3=[r2],8*10;;
 //      mov		cr119=r3                    // cr.cmcv
 
 restore_ARs:
-        add		r4=8,r2                  // duplicate r2 in r4
-        add		r6=2*8,r2;;              // duplicate r2 in r4
+	add		r4=8,r2                  // duplicate r2 in r4
+	add		r6=2*8,r2;;              // duplicate r2 in r4
 
-        ld8		r3=[r2],3*8
-        ld8		r5=[r4],3*8
-        ld8		r7=[r6],3*8;;
-        mov		ar0=r3                      // ar.kro
-        mov		ar1=r5                      // ar.kr1
-        mov		ar2=r7;;                    // ar.kr2
-
-        ld8		r3=[r2],3*8
-        ld8		r5=[r4],3*8
-        ld8		r7=[r6],3*8;;
-        mov		ar3=r3                      // ar.kr3                               
-        mov		ar4=r5                      // ar.kr4
-        mov		ar5=r7;;                    // ar.kr5
-
-        ld8		r3=[r2],10*8
-        ld8		r5=[r4],10*8
-        ld8		r7=[r6],10*8;;
-        mov		ar6=r3                      // ar.kr6
-        mov		ar7=r5                      // ar.kr7
+	ld8		r3=[r2],3*8
+	ld8		r5=[r4],3*8
+	ld8		r7=[r6],3*8;;
+	mov		ar0=r3                      // ar.kro
+	mov		ar1=r5                      // ar.kr1
+	mov		ar2=r7;;                    // ar.kr2
+
+	ld8		r3=[r2],3*8
+	ld8		r5=[r4],3*8
+	ld8		r7=[r6],3*8;;
+	mov		ar3=r3                      // ar.kr3
+	mov		ar4=r5                      // ar.kr4
+	mov		ar5=r7;;                    // ar.kr5
+
+	ld8		r3=[r2],10*8
+	ld8		r5=[r4],10*8
+	ld8		r7=[r6],10*8;;
+	mov		ar6=r3                      // ar.kr6
+	mov		ar7=r5                      // ar.kr7
 //      mov		ar8=r6                      // ar.kr8
-        ;;
+	;;
 
-        ld8		r3=[r2],3*8
-        ld8		r5=[r4],3*8
-        ld8		r7=[r6],3*8;;
+	ld8		r3=[r2],3*8
+	ld8		r5=[r4],3*8
+	ld8		r7=[r6],3*8;;
 //      mov		ar16=r3                     // ar.rsc
 //      mov		ar17=r5                     // ar.bsp is read only
 	mov		ar16=r0			    // make sure that RSE is in enforced lazy mode
 	;;
-        mov		ar18=r7;;                   // ar.bspstore
+	mov		ar18=r7;;                   // ar.bspstore
 
-        ld8		r9=[r2],8*13;;
-        mov		ar19=r9                     // ar.rnat
+	ld8		r9=[r2],8*13;;
+	mov		ar19=r9                     // ar.rnat
 
 	mov		ar16=r3			    // ar.rsc
-        ld8		r3=[r2],8*4;;
-        mov		ar32=r3                     // ar.ccv
+	ld8		r3=[r2],8*4;;
+	mov		ar32=r3                     // ar.ccv
 
-        ld8		r3=[r2],8*4;;
-        mov		ar36=r3                     // ar.unat
+	ld8		r3=[r2],8*4;;
+	mov		ar36=r3                     // ar.unat
 
-        ld8		r3=[r2],8*4;;
-        mov		ar40=r3                     // ar.fpsr
+	ld8		r3=[r2],8*4;;
+	mov		ar40=r3                     // ar.fpsr
 
-        ld8		r3=[r2],160;;               // 160
+	ld8		r3=[r2],160;;               // 160
 //      mov		ar44=r3                     // ar.itc
 
-        ld8		r3=[r2],8;;
-        mov		ar64=r3                     // ar.pfs
+	ld8		r3=[r2],8;;
+	mov		ar64=r3                     // ar.pfs
+
+	ld8		r3=[r2],8;;
+	mov		ar65=r3                     // ar.lc
 
-        ld8		r3=[r2],8;;
-        mov		ar65=r3                     // ar.lc
+	ld8		r3=[r2];;
+	mov		ar66=r3                     // ar.ec
+	add		r2=8*62,r2;;             // padding
 
-        ld8		r3=[r2];;
-        mov		ar66=r3                     // ar.ec
-        add		r2=8*62,r2;;             // padding 
-    
 restore_RRs:
-        mov		r5=ar.lc
-        mov		ar.lc=0x08-1
-        movl		r4=0x00
+	mov		r5=ar.lc
+	mov		ar.lc=0x08-1
+	movl		r4=0x00
 cStRRr:
-        ld8		r3=[r2],8;;
+	ld8		r3=[r2],8;;
 //      mov		rr[r4]=r3                   // what are its access previledges?
-        add		r4=1,r4
-        br.cloop.sptk.few	cStRRr
-        ;;
-        mov		ar.lc=r5
+	add		r4=1,r4
+	br.cloop.sptk.few	cStRRr
+	;;
+	mov		ar.lc=r5
 	;;
 end_os_mca_restore:
 	BRANCH(ia64_os_mca_done_restore, r2, p0, -0x20)
-	;; 
+	;;
 //EndStub//////////////////////////////////////////////////////////////////////
 
 // ok, the issue here is that we need to save state information so
@@ -647,16 +638,16 @@
 // In order to do this, our best bet is save the current state (plus
 // the state information obtain from the MIN_STATE_AREA) into a pt_regs
 // format.  This way we can pass it on in a useable format.
-//				
+//
 
 //
 // SAL to OS entry point for INIT on the monarch processor
-// This has been defined for registration purposes with SAL 
+// This has been defined for registration purposes with SAL
 // as a part of ia64_mca_init.
 //
 // When we get here, the follow registers have been
 // set by the SAL for our use
-//		
+//
 //		1. GR1 = OS INIT GP
 //		2. GR8 = PAL_PROC physical address
 //		3. GR9 = SAL_PROC physical address
@@ -665,14 +656,14 @@
 //			0 = Received INIT for event other than crash dump switch
 //			1 = Received wakeup at the end of an OS_MCA corrected machine check
 //			2 = Received INIT dude to CrashDump switch assertion
-//	
+//
 //		6. GR12 = Return address to location within SAL_INIT procedure
 
-				
+
 	.text
 	.align 16
-.global ia64_monarch_init_handler       
-.proc ia64_monarch_init_handler       
+.global ia64_monarch_init_handler
+.proc ia64_monarch_init_handler
 ia64_monarch_init_handler:
 
 #if defined(CONFIG_SMP) && defined(SAL_MPINIT_WORKAROUND)
@@ -680,6 +671,7 @@
 	// work around SAL bug that sends all processors to monarch entry
 	//
 	mov	r17=cr.lid
+	// XXX fix me: this is wrong: hard_smp_processor_id() is a pair of lid/eid
 	movl	r18=__cpu_physical_id
 	;;
 	dep	r18=0,r18,61,3		// convert to physical address
@@ -694,7 +686,7 @@
 	;;
 #endif
 
-	
+
 //
 // ok, the first thing we do is stash the information
 // the SAL passed to os
@@ -706,8 +698,8 @@
 	;;
 	st8	[_tmp]=r1,0x08;;
 	st8	[_tmp]=r8,0x08;;
-	st8	[_tmp]=r9,0x08;;			
-	st8	[_tmp]=r10,0x08;;			
+	st8	[_tmp]=r9,0x08;;
+	st8	[_tmp]=r10,0x08;;
 	st8	[_tmp]=r11,0x08;;
 	st8	[_tmp]=r12,0x08;;
 
@@ -719,12 +711,12 @@
 	adds r3=8,r2				// set up second base pointer
 	;;
 	SAVE_REST
-	
+
 // ok, enough should be saved at this point to be dangerous, and  supply
 // information for a dump
 // We need to switch to Virtual mode before hitting the C functions.
 //
-// 
+//
 //
 	movl	r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN
 	mov	r3=psr	// get the current psr, minimum enabled at this point
@@ -739,7 +731,7 @@
 	rfi
 	;;
 IVirtual_Switch:
-	//	
+	//
 	// We should now be running virtual
 	//
 	// Lets call the C handler to get the rest of the state info
@@ -759,7 +751,7 @@
 
 //
 // SAL to OS entry point for INIT on the slave processor
-// This has been defined for registration purposes with SAL 
+// This has been defined for registration purposes with SAL
 // as a part of ia64_mca_init.
 //
 
@@ -767,10 +759,10 @@
 	.align 16
 .global ia64_slave_init_handler
 .proc ia64_slave_init_handler
-ia64_slave_init_handler:		
+ia64_slave_init_handler:
 
 
-slave_init_spin_me:	
+slave_init_spin_me:
 	br.sptk slave_init_spin_me
 	;;
 	.endp
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/minstate.h linux/arch/ia64/kernel/minstate.h
--- v2.4.3/linux/arch/ia64/kernel/minstate.h	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/minstate.h	Thu Apr  5 12:51:47 2001
@@ -29,20 +29,20 @@
  */
 #define MINSTATE_START_SAVE_MIN_VIRT								\
 	dep r1=-1,r1,61,3;				/* r1 = current (virtual) */		\
-(p7)	mov ar.rsc=r0;		/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */	\
+(pUser)	mov ar.rsc=0;		/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */	\
 	;;											\
-(p7)	addl rKRBS=IA64_RBS_OFFSET,r1;			/* compute base of RBS */		\
-(p7)	mov rARRNAT=ar.rnat;									\
+(pUser)	addl rKRBS=IA64_RBS_OFFSET,r1;			/* compute base of RBS */		\
+(pUser)	mov rARRNAT=ar.rnat;									\
 (pKern) mov r1=sp;					/* get sp  */				\
 	;;											\
-(p7)	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;	/* compute base of memory stack */	\
-(p7)	mov rARBSPSTORE=ar.bspstore;			/* save ar.bspstore */			\
+(pUser)	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;	/* compute base of memory stack */	\
+(pUser)	mov rARBSPSTORE=ar.bspstore;			/* save ar.bspstore */			\
 	;;											\
 (pKern) addl r1=-IA64_PT_REGS_SIZE,r1;			/* if in kernel mode, use sp (r12) */	\
-(p7)	mov ar.bspstore=rKRBS;				/* switch to kernel RBS */		\
+(pUser)	mov ar.bspstore=rKRBS;				/* switch to kernel RBS */		\
 	;;											\
-(p7)	mov r18=ar.bsp;										\
-(p7)	mov ar.rsc=0x3;		/* set eager mode, pl 0, little-endian, loadrs=0 */		\
+(pUser)	mov r18=ar.bsp;										\
+(pUser)	mov ar.rsc=0x3;		/* set eager mode, pl 0, little-endian, loadrs=0 */		\
 
 #define MINSTATE_END_SAVE_MIN_VIRT								\
 	or r13=r13,r14;		/* make `current' a kernel virtual address */			\
@@ -55,20 +55,20 @@
  */
 #define MINSTATE_START_SAVE_MIN_PHYS								\
 (pKern) movl sp=ia64_init_stack+IA64_STK_OFFSET-IA64_PT_REGS_SIZE;				\
-(p7)	mov ar.rsc=r0;		/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */	\
-(p7)	addl rKRBS=IA64_RBS_OFFSET,r1;		/* compute base of register backing store */	\
+(pUser)	mov ar.rsc=0;		/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */	\
+(pUser)	addl rKRBS=IA64_RBS_OFFSET,r1;		/* compute base of register backing store */	\
 	;;											\
-(p7)	mov rARRNAT=ar.rnat;									\
+(pUser)	mov rARRNAT=ar.rnat;									\
 (pKern) dep r1=0,sp,61,3;				/* compute physical addr of sp	*/	\
-(p7)	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;	/* compute base of memory stack */	\
-(p7)	mov rARBSPSTORE=ar.bspstore;			/* save ar.bspstore */			\
-(p7)	dep rKRBS=-1,rKRBS,61,3;			/* compute kernel virtual addr of RBS */\
+(pUser)	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;	/* compute base of memory stack */	\
+(pUser)	mov rARBSPSTORE=ar.bspstore;			/* save ar.bspstore */			\
+(pUser)	dep rKRBS=-1,rKRBS,61,3;			/* compute kernel virtual addr of RBS */\
 	;;											\
 (pKern) addl r1=-IA64_PT_REGS_SIZE,r1;		/* if in kernel mode, use sp (r12) */		\
-(p7)	mov ar.bspstore=rKRBS;			/* switch to kernel RBS */			\
+(pUser)	mov ar.bspstore=rKRBS;			/* switch to kernel RBS */			\
 	;;											\
-(p7)	mov r18=ar.bsp;										\
-(p7)	mov ar.rsc=0x3;		/* set eager mode, pl 0, little-endian, loadrs=0 */		\
+(pUser)	mov r18=ar.bsp;										\
+(pUser)	mov ar.rsc=0x3;		/* set eager mode, pl 0, little-endian, loadrs=0 */		\
 
 #define MINSTATE_END_SAVE_MIN_PHYS								\
 	or r12=r12,r14;		/* make sp a kernel virtual address */				\
@@ -101,29 +101,30 @@
  *	r12 = kernel sp (kernel virtual address)
  *	r13 = points to current task_struct (kernel virtual address)
  *	p15 = TRUE if psr.i is set in cr.ipsr
- *	predicate registers (other than p6, p7, and p15), b6, r3, r8, r9, r10, r11, r14, r15:
+ *	predicate registers (other than p2, p3, and p15), b6, r3, r8, r9, r10, r11, r14, r15:
  *		preserved
  *
  * Note that psr.ic is NOT turned on by this macro.  This is so that
  * we can pass interruption state as arguments to a handler.
  */
-#define DO_SAVE_MIN(COVER,EXTRA)								  \
+#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA)							  \
 	mov rARRSC=ar.rsc;									  \
 	mov rARPFS=ar.pfs;									  \
 	mov rR1=r1;										  \
 	mov rARUNAT=ar.unat;									  \
 	mov rCRIPSR=cr.ipsr;									  \
-	mov rB6=b6;		/* rB6 = branch reg 6 */					  \
+	mov rB6=b6;				/* rB6 = branch reg 6 */			  \
 	mov rCRIIP=cr.iip;									  \
-	mov r1=ar.k6;		/* r1 = current (physical) */					  \
+	mov r1=IA64_KR(CURRENT);		/* r1 = current (physical) */			  \
+	COVER;											  \
 	;;											  \
 	invala;											  \
 	extr.u r16=rCRIPSR,32,2;		/* extract psr.cpl */				  \
 	;;											  \
-	cmp.eq pKern,p7=r0,r16;			/* are we in kernel mode already? (psr.cpl==0) */ \
+	cmp.eq pKern,pUser=r0,r16;		/* are we in kernel mode already? (psr.cpl==0) */ \
 	/* switch from user to kernel RBS: */							  \
-	COVER;											  \
 	;;											  \
+	SAVE_IFS;										  \
 	MINSTATE_START_SAVE_MIN									  \
 	;;											  \
 	mov r16=r1;					/* initialize first base pointer */	  \
@@ -135,7 +136,7 @@
 	;;											  \
 	st8 [r16]=rCRIFS,16;	/* save cr.ifs */						  \
 	st8 [r17]=rARUNAT,16;	/* save ar.unat */						  \
-(p7)	sub r18=r18,rKRBS;	/* r18=RSE.ndirty*8 */						  \
+(pUser)	sub r18=r18,rKRBS;	/* r18=RSE.ndirty*8 */						  \
 	;;											  \
 	st8 [r16]=rARPFS,16;	/* save ar.pfs */						  \
 	st8 [r17]=rARRSC,16;	/* save ar.rsc */						  \
@@ -143,8 +144,8 @@
 	;;			/* avoid RAW on r16 & r17 */					  \
 (pKern)	adds r16=16,r16;	/* skip over ar_rnat field */					  \
 (pKern)	adds r17=16,r17;	/* skip over ar_bspstore field */				  \
-(p7)	st8 [r16]=rARRNAT,16;	/* save ar.rnat */						  \
-(p7)	st8 [r17]=rARBSPSTORE,16;	/* save ar.bspstore */					  \
+(pUser)	st8 [r16]=rARRNAT,16;	/* save ar.rnat */						  \
+(pUser)	st8 [r17]=rARBSPSTORE,16;	/* save ar.bspstore */					  \
 	;;											  \
 	st8 [r16]=rARPR,16;	/* save predicates */						  \
 	st8 [r17]=rB6,16;	/* save b6 */							  \
@@ -171,7 +172,7 @@
 	;;											  \
 .mem.offset 0,0;		st8.spill [r16]=r10,16;						  \
 .mem.offset 8,0;		st8.spill [r17]=r11,16;						  \
-	mov r13=ar.k6;		/* establish `current' */					  \
+	mov r13=IA64_KR(CURRENT);	/* establish `current' */				  \
 	;;											  \
 	EXTRA;											  \
 	movl r1=__gp;		/* establish kernel global pointer */				  \
@@ -240,6 +241,6 @@
 # define STOPS
 #endif
 
-#define SAVE_MIN_WITH_COVER	DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs,) STOPS
-#define SAVE_MIN_WITH_COVER_R19	DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs, mov r15=r19) STOPS
-#define SAVE_MIN		DO_SAVE_MIN(mov rCRIFS=r0,) STOPS
+#define SAVE_MIN_WITH_COVER	DO_SAVE_MIN(cover, mov rCRIFS=cr.ifs,) STOPS
+#define SAVE_MIN_WITH_COVER_R19	DO_SAVE_MIN(cover, mov rCRIFS=cr.ifs, mov r15=r19) STOPS
+#define SAVE_MIN		DO_SAVE_MIN(     , mov rCRIFS=r0, ) STOPS
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/pal.S linux/arch/ia64/kernel/pal.S
--- v2.4.3/linux/arch/ia64/kernel/pal.S	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/pal.S	Thu Apr  5 12:51:47 2001
@@ -14,11 +14,6 @@
 #include <asm/asmmacro.h>
 #include <asm/processor.h>
 
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 	.data
 pal_entry_point:
 	data8 ia64_pal_default_handler
@@ -58,7 +53,7 @@
  *
  */
 GLOBAL_ENTRY(ia64_pal_call_static)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(6))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(6)
 	alloc loc1 = ar.pfs,6,90,0,0
 	movl loc2 = pal_entry_point
 1:	{
@@ -73,7 +68,7 @@
 	;;
 	mov loc3 = psr
 	mov loc0 = rp
-	UNW(.body)
+	.body
 	mov r30 = in2
 
 (p6)	rsm psr.i | psr.ic
@@ -101,14 +96,14 @@
  * 	in2 - in3   Remaning PAL arguments
  */
 GLOBAL_ENTRY(ia64_pal_call_stacked)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
 	alloc loc1 = ar.pfs,5,4,87,0
 	movl loc2 = pal_entry_point
 
 	mov r28  = in0			// Index MUST be copied to r28
 	mov out0 = in0			// AND in0 of PAL function
 	mov loc0 = rp
-	UNW(.body)
+	.body
 	;;
 	ld8 loc2 = [loc2]		// loc2 <- entry point
 	mov out1 = in1
@@ -148,7 +143,7 @@
 
 
 GLOBAL_ENTRY(ia64_pal_call_phys_static)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(6))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(6)
 	alloc loc1 = ar.pfs,6,90,0,0
 	movl loc2 = pal_entry_point
 1:	{
@@ -156,7 +151,7 @@
 	  mov r8   = ip			// save ip to compute branch
 	  mov loc0 = rp			// save rp
 	}
-	UNW(.body)
+	.body
 	;;
 	ld8 loc2 = [loc2]		// loc2 <- entry point
 	mov r29  = in1			// first argument
@@ -171,7 +166,7 @@
 	dep.z r8=r8,0,61		// convert rp to physical
 	;;
 	mov b7 = loc2			// install target to branch reg
-	mov ar.rsc=r0			// put RSE in enforced lazy, LE mode
+	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	movl r16=PAL_PSR_BITS_TO_CLEAR
 	movl r17=PAL_PSR_BITS_TO_SET
 	;;
@@ -182,7 +177,7 @@
 .ret1:	mov rp = r8			// install return address (physical)
 	br.cond.sptk.few b7
 1:
-	mov ar.rsc=r0			// put RSE in enforced lazy, LE mode
+	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	mov r16=loc3			// r16= original psr
 	br.call.sptk.few rp=ia64_switch_mode // return to virtual mode
 .ret2:
@@ -204,7 +199,7 @@
  * 	in2 - in3   Remaning PAL arguments
  */
 GLOBAL_ENTRY(ia64_pal_call_phys_stacked)
-	UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5))
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
 	alloc	loc1 = ar.pfs,5,5,86,0
 	movl	loc2 = pal_entry_point
 1:	{
@@ -224,7 +219,7 @@
 	mov loc4=ar.rsc			// save RSE configuration
 	dep.z loc2=loc2,0,61		// convert pal entry point to physical
 	;;
-	mov ar.rsc=r0			// put RSE in enforced lazy, LE mode
+	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	movl r16=PAL_PSR_BITS_TO_CLEAR
 	movl r17=PAL_PSR_BITS_TO_SET
 	;;
@@ -236,7 +231,7 @@
 .ret6:
 	br.call.sptk.many rp=b7		// now make the call
 .ret7:
-	mov ar.rsc=r0			// put RSE in enforced lazy, LE mode
+	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	mov r16=loc3			// r16= original psr
 	br.call.sptk.few rp=ia64_switch_mode	// return to virtual mode
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/palinfo.c linux/arch/ia64/kernel/palinfo.c
--- v2.4.3/linux/arch/ia64/kernel/palinfo.c	Fri Feb 16 15:53:08 2001
+++ linux/arch/ia64/kernel/palinfo.c	Thu Apr  5 12:51:47 2001
@@ -5,16 +5,13 @@
  * This code is based on specification of PAL as of the
  * Intel IA-64 Architecture Software Developer's Manual v1.0.
  *
- * 
+ *
  * Copyright (C) 2000 Hewlett-Packard Co
  * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
- * 
+ *
  * 05/26/2000	S.Eranian	initial release
  * 08/21/2000	S.Eranian	updated to July 2000 PAL specs
- *
- * ISSUES:
- *	- as of 2.2.9/2.2.12, the following values are still wrong
- *		PAL_VM_SUMMARY: key & rid sizes
+ * 02/05/2001   S.Eranian	fixed module support
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -36,12 +33,7 @@
 MODULE_AUTHOR("Stephane Eranian <eranian@hpl.hp.com>");
 MODULE_DESCRIPTION("/proc interface to IA-64 PAL");
 
-/*
- * Hope to get rid of this one in a near future
-*/
-#define IA64_PAL_VERSION_BUG		1
-
-#define PALINFO_VERSION "0.3"
+#define PALINFO_VERSION "0.4"
 
 #ifdef CONFIG_SMP
 #define cpu_is_online(i) (cpu_online_map & (1UL << i))
@@ -83,7 +75,7 @@
 	"Non-temporal, all levels",
 	"Reserved",
 	"Reserved",
-	"Reserved",	
+	"Reserved",
 	"Reserved"
 };
 
@@ -94,7 +86,7 @@
 	"Non-temporal, all levels",
 	"Reserved",
 	"Reserved",
-	"Reserved",	
+	"Reserved",
 	"Reserved"
 };
 
@@ -108,7 +100,7 @@
 #define RSE_HINTS_COUNT (sizeof(rse_hints)/sizeof(const char *))
 
 /*
- * The current revision of the Volume 2 (July 2000) of 
+ * The current revision of the Volume 2 (July 2000) of
  * IA-64 Architecture Software Developer's Manual is wrong.
  * Table 4-10 has invalid information concerning the ma field:
  * Correct table is:
@@ -116,7 +108,7 @@
  *      bit 4 - 100 - UC
  *      bit 5 - 101 - UCE
  *      bit 6 - 110 - WC
- *      bit 7 - 111 - NatPage 
+ *      bit 7 - 111 - NatPage
  */
 static const char *mem_attrib[]={
 	"Write Back (WB)",		/* 000 */
@@ -136,7 +128,7 @@
  *
  * Input:
  *	- a pointer to a buffer to hold the string
- * 	- a 64-bit vector
+ *	- a 64-bit vector
  * Ouput:
  *	- a pointer to the end of the buffer
  *
@@ -163,7 +155,7 @@
  *
  * Input:
  *	- a pointer to a buffer to hold the string
- * 	- a 64-bit vector
+ *	- a 64-bit vector
  * Ouput:
  *	- a pointer to the end of the buffer
  *
@@ -181,7 +173,7 @@
 		if (i != 0 && (i%64) == 0) value = *++reg_info;
 
 		if ((value & 0x1) == 0 && skip == 0) {
-			if (begin  <= i - 2) 
+			if (begin  <= i - 2)
 				p += sprintf(p, "%d-%d ", begin, i-1);
 			else
 				p += sprintf(p, "%d ", i-1);
@@ -194,7 +186,7 @@
 		value >>=1;
 	}
 	if (begin > -1) {
-		if (begin < 127) 
+		if (begin < 127)
 			p += sprintf(p, "%d-127", begin);
 		else
 			p += sprintf(p, "127");
@@ -219,7 +211,7 @@
 		if (halt_info[i].pal_power_mgmt_info_s.im == 1) {
 			p += sprintf(p,	"Power level %d:\n" \
 					"\tentry_latency       : %d cycles\n" \
-				 	"\texit_latency        : %d cycles\n" \
+					"\texit_latency        : %d cycles\n" \
 					"\tpower consumption   : %d mW\n" \
 					"\tCache+TLB coherency : %s\n", i,
 				halt_info[i].pal_power_mgmt_info_s.entry_latency,
@@ -233,7 +225,7 @@
 	return p - page;
 }
 
-static int 
+static int
 cache_info(char *page)
 {
 	char *p = page;
@@ -288,13 +280,13 @@
 
 			for(k=0; k < 8; k++ ) {
 				if ( cci.pcci_st_hints & 0x1) p += sprintf(p, "[%s]", cache_st_hints[k]);
-				cci.pcci_st_hints >>=1; 
+				cci.pcci_st_hints >>=1;
 			}
 			p += sprintf(p, "\n\tLoad hints     : ");
 
 			for(k=0; k < 8; k++ ) {
 				if ( cci.pcci_ld_hints & 0x1) p += sprintf(p, "[%s]", cache_ld_hints[k]);
-				cci.pcci_ld_hints >>=1; 
+				cci.pcci_ld_hints >>=1;
 			}
 			p += sprintf(p, "\n\tAlias boundary : %d byte(s)\n" \
 					"\tTag LSB        : %d\n" \
@@ -384,7 +376,7 @@
 			ptce.stride[1]);
 
 	p += sprintf(p, "TC Levels                      : %d\n" \
-			"Unique TC(s)                   : %d\n", 
+			"Unique TC(s)                   : %d\n",
 			vm_info_1.pal_vm_info_1_s.num_tc_levels,
 			vm_info_1.pal_vm_info_1_s.max_unique_tcs);
 
@@ -392,7 +384,7 @@
 		for (j=2; j>0 ; j--) {
 			tc_pages = 0; /* just in case */
 
-		
+
 			/* even without unification, some levels may not be present */
 			if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
 				continue;
@@ -422,7 +414,7 @@
 	}
 	p += sprintf(p, "\n");
 
-	return p - page;	
+	return p - page;
 }
 
 
@@ -446,7 +438,7 @@
 
 		if (ia64_pal_register_info(info, &reg_info[0], &reg_info[1]) != 0) return 0;
 
-	 	p += sprintf(p, "%-32s : ", info_type[info]);
+		p += sprintf(p, "%-32s : ", info_type[info]);
 
 		p = bitregister_process(p, reg_info, 128);
 
@@ -458,8 +450,8 @@
 	p += sprintf(p, "RSE stacked physical registers   : %ld\n" \
 			"RSE load/store hints             : %ld (%s)\n",
 			phys_stacked,
-			hints.ph_data, 
-		     	hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)");
+			hints.ph_data,
+			hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)");
 
 	if (ia64_pal_debug_info(&iregs, &dregs)) return 0;
 
@@ -486,15 +478,15 @@
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	"Disable BINIT on processor time-out",
 	"Disable dynamic power management (DPM)",
-	"Disable coherency", 
-	"Disable cache", 
+	"Disable coherency",
+	"Disable cache",
 	"Enable CMCI promotion",
 	"Enable MCA to BINIT promotion",
 	"Enable MCA promotion",
 	"Enable BEER promotion"
 };
 
-	
+
 static int
 processor_info(char *page)
 {
@@ -508,7 +500,7 @@
 
 	for(i=0; i < 64; i++, v++,avail >>=1, status >>=1, control >>=1) {
 		if ( ! *v ) continue;
-		p += sprintf(p, "%-40s : %s%s %s\n", *v, 
+		p += sprintf(p, "%-40s : %s%s %s\n", *v,
 				avail & 0x1 ? "" : "NotImpl",
 				avail & 0x1 ? (status & 0x1 ? "On" : "Off"): "",
 				avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
@@ -526,9 +518,9 @@
 	"Enable Half Transfer",
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, 
-	"Enable Cache Line Repl. Exclusive", 
-	"Enable Cache Line Repl. Shared", 
+	NULL, NULL, NULL, NULL,
+	"Enable Cache Line Repl. Exclusive",
+	"Enable Cache Line Repl. Shared",
 	"Disable Transaction Queuing",
 	"Disable Reponse Error Checking",
 	"Disable Bus Error Checking",
@@ -541,7 +533,7 @@
 	"Disable Bus Data Error Checking"
 };
 
-	
+
 static int
 bus_info(char *page)
 {
@@ -560,7 +552,7 @@
 
 	for(i=0; i < 64; i++, v++, avail >>=1, status >>=1, control >>=1) {
 		if ( ! *v ) continue;
-		p += sprintf(p, "%-48s : %s%s %s\n", *v, 
+		p += sprintf(p, "%-48s : %s%s %s\n", *v,
 				avail & 0x1 ? "" : "NotImpl",
 				avail & 0x1 ? (status  & 0x1 ? "On" : "Off"): "",
 				avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): "");
@@ -568,62 +560,39 @@
 	return p - page;
 }
 
-
-/*
- * physical mode call for PAL_VERSION is working fine.
- * This function is meant to go away once PAL get fixed.
- */
-static inline s64 
-ia64_pal_version_phys(pal_version_u_t *pal_min_version, pal_version_u_t *pal_cur_version) 
-{	
-	struct ia64_pal_retval iprv;
-	PAL_CALL_PHYS(iprv, PAL_VERSION, 0, 0, 0);
-	if (pal_min_version)
-		pal_min_version->pal_version_val = iprv.v0;
-	if (pal_cur_version)
-		pal_cur_version->pal_version_val = iprv.v1;
-	return iprv.status; 
-}
-
 static int
 version_info(char *page)
 {
-	s64 status;
 	pal_version_u_t min_ver, cur_ver;
 	char *p = page;
 
-#ifdef IA64_PAL_VERSION_BUG
-	/* The virtual mode call is buggy. But the physical mode call seems
-	 * to be ok. Until they fix virtual mode, we do physical.
-	 */
-	status = ia64_pal_version_phys(&min_ver, &cur_ver);
-#else
-	/* The system crashes if you enable this code with the wrong PAL 
-	 * code
+	/* The PAL_VERSION call is advertised as being able to support
+	 * both physical and virtual mode calls. This seems to be a documentation
+	 * bug rather than firmware bug. In fact, it does only support physical mode.
+	 * So now the code reflects this fact and the pal_version() has been updated
+	 * accordingly.
 	 */
-	status = ia64_pal_version(&min_ver, &cur_ver);
-#endif
-	if (status != 0) return 0;
+	if (ia64_pal_version(&min_ver, &cur_ver) != 0) return 0;
 
 	p += sprintf(p, "PAL_vendor : 0x%02x (min=0x%02x)\n" \
 			"PAL_A      : %x.%x.%x (min=%x.%x.%x)\n" \
 			"PAL_B      : %x.%x.%x (min=%x.%x.%x)\n",
-	     		cur_ver.pal_version_s.pv_pal_vendor,
-	     		min_ver.pal_version_s.pv_pal_vendor,
+			cur_ver.pal_version_s.pv_pal_vendor,
+			min_ver.pal_version_s.pv_pal_vendor,
 
-	     		cur_ver.pal_version_s.pv_pal_a_model>>4,
-	     		cur_ver.pal_version_s.pv_pal_a_model&0xf,
-	     		cur_ver.pal_version_s.pv_pal_a_rev,
-	     		min_ver.pal_version_s.pv_pal_a_model>>4,
-	     		min_ver.pal_version_s.pv_pal_a_model&0xf,
-	     		min_ver.pal_version_s.pv_pal_a_rev,
-
-	     		cur_ver.pal_version_s.pv_pal_b_model>>4,
-	     		cur_ver.pal_version_s.pv_pal_b_model&0xf,
-	     		cur_ver.pal_version_s.pv_pal_b_rev,
-	     		min_ver.pal_version_s.pv_pal_b_model>>4,
-	     		min_ver.pal_version_s.pv_pal_b_model&0xf,
-	     		min_ver.pal_version_s.pv_pal_b_rev);
+			cur_ver.pal_version_s.pv_pal_a_model>>4,
+			cur_ver.pal_version_s.pv_pal_a_model&0xf,
+			cur_ver.pal_version_s.pv_pal_a_rev,
+			min_ver.pal_version_s.pv_pal_a_model>>4,
+			min_ver.pal_version_s.pv_pal_a_model&0xf,
+			min_ver.pal_version_s.pv_pal_a_rev,
+
+			cur_ver.pal_version_s.pv_pal_b_model>>4,
+			cur_ver.pal_version_s.pv_pal_b_model&0xf,
+			cur_ver.pal_version_s.pv_pal_b_rev,
+			min_ver.pal_version_s.pv_pal_b_model>>4,
+			min_ver.pal_version_s.pv_pal_b_model&0xf,
+			min_ver.pal_version_s.pv_pal_b_rev);
 
 	return p - page;
 }
@@ -650,7 +619,7 @@
 			"Counter width                 : %d bits\n" \
 			"Cycle event number            : %d\n" \
 			"Retired event number          : %d\n" \
-			"Implemented PMC               : ", 
+			"Implemented PMC               : ",
 			pm_info.pal_perf_mon_info_s.generic,
 			pm_info.pal_perf_mon_info_s.width,
 			pm_info.pal_perf_mon_info_s.cycles,
@@ -659,15 +628,15 @@
 	p = bitregister_process(p, pm_buffer, 256);
 
 	p += sprintf(p, "\nImplemented PMD               : ");
-	
+
 	p = bitregister_process(p, pm_buffer+4, 256);
 
 	p += sprintf(p, "\nCycles count capable          : ");
-	
+
 	p = bitregister_process(p, pm_buffer+8, 256);
 
 	p += sprintf(p, "\nRetired bundles count capable : ");
-	
+
 	p = bitregister_process(p, pm_buffer+12, 256);
 
 	p += sprintf(p, "\n");
@@ -683,7 +652,7 @@
 	u64 base;
 
 	if (ia64_pal_freq_base(&base) == -1)
-		p += sprintf(p, "Output clock            : not implemented\n"); 
+		p += sprintf(p, "Output clock            : not implemented\n");
 	else
 		p += sprintf(p, "Output clock            : %ld ticks/s\n", base);
 
@@ -762,7 +731,7 @@
 
 		if (ifa_reg->valid == 0) continue;
 
-		gr_reg   = (struct gr_reg *)tr_buffer;	
+		gr_reg   = (struct gr_reg *)tr_buffer;
 		itir_reg = (struct itir_reg *)&tr_buffer[1];
 		rid_reg  = (struct rid_reg *)&tr_buffer[3];
 
@@ -788,7 +757,7 @@
 				"\trid  : %x\n" \
 				"\tp    : %d\n" \
 				"\tma   : %d\n" \
-				"\td    : %d\n", 
+				"\td    : %d\n",
 				gr_reg->pl,
 				gr_reg->ar,
 				rid_reg->rid,
@@ -807,7 +776,7 @@
  */
 static palinfo_entry_t palinfo_entries[]={
 	{ "version_info",	version_info, },
-	{ "vm_info", 		vm_info, },
+	{ "vm_info",		vm_info, },
 	{ "cache_info",		cache_info, },
 	{ "power_info",		power_info, },
 	{ "register_info",	register_info, },
@@ -821,14 +790,14 @@
 #define NR_PALINFO_ENTRIES	(sizeof(palinfo_entries)/sizeof(palinfo_entry_t))
 
 /*
- * this array is used to keep track of the proc entries we create. This is 
+ * this array is used to keep track of the proc entries we create. This is
  * required in the module mode when we need to remove all entries. The procfs code
  * does not do recursion of deletion
  *
  * Notes:
  *	- first +1 accounts for the cpuN entry
  *	- second +1 account for toplevel palinfo
- * 
+ *
  */
 #define NR_PALINFO_PROC_ENTRIES	(NR_CPUS*(NR_PALINFO_ENTRIES+1)+1)
 
@@ -855,7 +824,7 @@
 #ifdef CONFIG_SMP
 
 /*
- * used to hold information about final function to call 
+ * used to hold information about final function to call
  */
 typedef struct {
 	palinfo_func_t	func;	/* pointer to function to call */
@@ -888,7 +857,7 @@
  *	0 : error or nothing to output
  *	otherwise how many bytes in the "page" buffer were written
  */
-static 
+static
 int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
 {
 	palinfo_smp_data_t ptr;
@@ -908,7 +877,7 @@
 	return ptr.ret;
 }
 #else /* ! CONFIG_SMP */
-static 
+static
 int palinfo_handle_smp(pal_func_cpu_u_t *f, char *page)
 {
 	printk(__FUNCTION__" should not be called with non SMP kernel\n");
@@ -930,25 +899,25 @@
 	 * in SMP mode, we may need to call another CPU to get correct
 	 * information. PAL, by definition, is processor specific
 	 */
-	if (f->req_cpu == smp_processor_id()) 
+	if (f->req_cpu == smp_processor_id())
 		len = (*palinfo_entries[f->func_id].proc_read)(page);
 	else
 		len = palinfo_handle_smp(f, page);
 
-        if (len <= off+count) *eof = 1;
+	if (len <= off+count) *eof = 1;
 
-        *start = page + off;
-        len   -= off;
+	*start = page + off;
+	len   -= off;
 
-        if (len>count) len = count;
-        if (len<0) len = 0;
+	if (len>count) len = count;
+	if (len<0) len = 0;
 
 	MOD_DEC_USE_COUNT;
 
-        return len;
+	return len;
 }
 
-static int __init 
+static int __init
 palinfo_init(void)
 {
 #	define CPUSTR	"cpu%d"
@@ -979,7 +948,7 @@
 
 		for (j=0; j < NR_PALINFO_ENTRIES; j++) {
 			f.func_id = j;
-			*pdir++ = create_proc_read_entry (palinfo_entries[j].name, 0, cpu_dir, 
+			*pdir++ = create_proc_read_entry (palinfo_entries[j].name, 0, cpu_dir,
 						palinfo_read_entry, (void *)f.value);
 		}
 		*pdir++ = cpu_dir;
@@ -994,9 +963,10 @@
 {
 	int i = 0;
 
-	/* remove all nodes: depth first pass */
+	/* remove all nodes: depth first pass. Could optimize this  */
 	for (i=0; i< NR_PALINFO_PROC_ENTRIES ; i++) {
-		remove_proc_entry (palinfo_proc_entries[i]->name, NULL);
+		if (palinfo_proc_entries[i])
+			remove_proc_entry (palinfo_proc_entries[i]->name, NULL);
 	}
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/perfmon.c linux/arch/ia64/kernel/perfmon.c
--- v2.4.3/linux/arch/ia64/kernel/perfmon.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/perfmon.c	Fri Apr 13 15:29:37 2001
@@ -7,57 +7,39 @@
  * Modifications by Stephane Eranian, Hewlett-Packard Co.
  * Copyright (C) 1999 Ganesh Venkitachalam <venkitac@us.ibm.com>
  * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 2000-2001 Stephane Eranian <eranian@hpl.hp.com>
  */
 
 #include <linux/config.h>
-
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/wrapper.h>
+#include <linux/mm.h>
 
+#include <asm/bitops.h>
+#include <asm/efi.h>
 #include <asm/errno.h>
 #include <asm/hw_irq.h>
+#include <asm/page.h>
+#include <asm/pal.h>
+#include <asm/perfmon.h>
+#include <asm/pgtable.h>
 #include <asm/processor.h>
+#include <asm/signal.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/pal.h>
-
-/* Long blurb on how this works: 
- * We set dcr.pp, psr.pp, and the appropriate pmc control values with
- * this.  Notice that we go about modifying _each_ task's pt_regs to
- * set cr_ipsr.pp.  This will start counting when "current" does an
- * _rfi_. Also, since each task's cr_ipsr.pp, and cr_ipsr is inherited
- * across forks, we do _not_ need additional code on context
- * switches. On stopping of the counters we dont need to go about
- * changing every task's cr_ipsr back to where it wuz, because we can
- * just set pmc[0]=1. But we do it anyways becuase we will probably
- * add thread specific accounting later.
- *
- * The obvious problem with this is that on SMP systems, it is a bit
- * of work (when someone wants to do it:-)) - it would be easier if we
- * just added code to the context-switch path, but if we wanted to support
- * per-thread accounting, the context-switch path might be long unless 
- * we introduce a flag in the task_struct. Right now, the following code 
- * will NOT work correctly on MP (for more than one reason:-)).
- *
- * The short answer is that to make this work on SMP,  we would need 
- * to lock the run queue to ensure no context switches, send 
- * an IPI to each processor, and in that IPI handler, set processor regs,
- * and just modify the psr bit of only the _current_ thread, since we have 
- * modified the psr bit correctly in the kernel stack for every process 
- * which is not running. Also, we need pmd arrays per-processor, and 
- * the READ_PMD command will need to get values off of other processors. 
- * IPIs are the answer, irrespective of what the question is. Might 
- * crash on SMP systems without the lock_kernel().
- */
+#include <asm/delay.h> /* for ia64_get_itc() */
 
 #ifdef CONFIG_PERFMON
 
-#define MAX_PERF_COUNTER	4	/* true for Itanium, at least */
+#define PFM_VERSION		"0.2"
+#define PFM_SMPL_HDR_VERSION	1
+
 #define PMU_FIRST_COUNTER	4	/* first generic counter */
 
 #define PFM_WRITE_PMCS		0xa0
@@ -67,293 +49,1019 @@
 #define PFM_START		0xa4
 #define PFM_ENABLE		0xa5	/* unfreeze only */
 #define PFM_DISABLE		0xa6	/* freeze only */
-/* 
+#define PFM_RESTART		0xcf
+#define PFM_CREATE_CONTEXT	0xa7
+/*
  * Those 2 are just meant for debugging. I considered using sysctl() for
  * that but it is a little bit too pervasive. This solution is at least
  * self-contained.
  */
-#define PFM_DEBUG_ON		0xe0	
+#define PFM_DEBUG_ON		0xe0
 #define PFM_DEBUG_OFF		0xe1
 
+
+/*
+ * perfmon API flags
+ */
+#define PFM_FL_INHERIT_NONE	 0x00	/* never inherit a context across fork (default) */
+#define PFM_FL_INHERIT_ONCE	 0x01	/* clone pfm_context only once across fork() */
+#define PFM_FL_INHERIT_ALL	 0x02	/* always clone pfm_context across fork() */
+#define PFM_FL_SMPL_OVFL_NOBLOCK 0x04	/* do not block on sampling buffer overflow */
+#define PFM_FL_SYSTEMWIDE	 0x08	/* create a systemwide context */
+
+/*
+ * PMC API flags
+ */
+#define PFM_REGFL_OVFL_NOTIFY	1		/* send notification on overflow */
+
+/*
+ * Private flags and masks
+ */
+#define PFM_FL_INHERIT_MASK	(PFM_FL_INHERIT_NONE|PFM_FL_INHERIT_ONCE|PFM_FL_INHERIT_ALL)
+
 #ifdef CONFIG_SMP
 #define cpu_is_online(i) (cpu_online_map & (1UL << i))
 #else
 #define cpu_is_online(i)	1
 #endif
 
-#define PMC_IS_IMPL(i)		(pmu_conf.impl_regs[i>>6] & (1<< (i&~(64-1))))
-#define PMD_IS_IMPL(i)  	(pmu_conf.impl_regs[4+(i>>6)] & (1<< (i&~(64-1))))
+#define PMC_IS_IMPL(i)		(i < pmu_conf.num_pmcs && pmu_conf.impl_regs[i>>6] & (1<< (i&~(64-1))))
+#define PMD_IS_IMPL(i)	(i < pmu_conf.num_pmds &&  pmu_conf.impl_regs[4+(i>>6)] & (1<< (i&~(64-1))))
 #define PMD_IS_COUNTER(i)	(i>=PMU_FIRST_COUNTER && i < (PMU_FIRST_COUNTER+pmu_conf.max_counters))
 #define PMC_IS_COUNTER(i)	(i>=PMU_FIRST_COUNTER && i < (PMU_FIRST_COUNTER+pmu_conf.max_counters))
 
+/* This is the Itanium-specific PMC layout for counter config */
+typedef struct {
+	unsigned long pmc_plm:4;	/* privilege level mask */
+	unsigned long pmc_ev:1;		/* external visibility */
+	unsigned long pmc_oi:1;		/* overflow interrupt */
+	unsigned long pmc_pm:1;		/* privileged monitor */
+	unsigned long pmc_ig1:1;	/* reserved */
+	unsigned long pmc_es:7;		/* event select */
+	unsigned long pmc_ig2:1;	/* reserved */
+	unsigned long pmc_umask:4;	/* unit mask */
+	unsigned long pmc_thres:3;	/* threshold */
+	unsigned long pmc_ig3:1;	/* reserved (missing from table on p6-17) */
+	unsigned long pmc_ism:2;	/* instruction set mask */
+	unsigned long pmc_ig4:38;	/* reserved */
+} pmc_counter_reg_t;
+
+/* test for EAR/BTB configuration */
+#define PMU_DEAR_EVENT	0x67
+#define PMU_IEAR_EVENT	0x23
+#define PMU_BTB_EVENT	0x11
+
+#define PMC_IS_DEAR(a)		(((pmc_counter_reg_t *)(a))->pmc_es == PMU_DEAR_EVENT)
+#define PMC_IS_IEAR(a)		(((pmc_counter_reg_t *)(a))->pmc_es == PMU_IEAR_EVENT)
+#define PMC_IS_BTB(a)		(((pmc_counter_reg_t *)(a))->pmc_es == PMU_BTB_EVENT)
+
 /*
- * this structure needs to be enhanced
+ * This header is at the beginning of the sampling buffer returned to the user.
+ * It is exported as Read-Only at this point. It is directly followed with the
+ * first record.
  */
 typedef struct {
-	unsigned long	pfr_reg_num;	/* which register */
-	unsigned long	pfr_reg_value;	/* configuration (PMC) or initial value (PMD) */
-	unsigned long	pfr_reg_reset;	/* reset value on overflow (PMD) */
-	void		*pfr_smpl_buf;	/* pointer to user buffer for EAR/BTB */
-	unsigned long	pfr_smpl_size;	/* size of user buffer for EAR/BTB */
-	pid_t		pfr_notify_pid;	/* process to notify */
-	int		pfr_notify_sig;	/* signal for notification, 0=no notification */
-} perfmon_req_t;
+	int		hdr_version;		/* could be used to differentiate formats */
+	int		hdr_reserved;
+	unsigned long	hdr_entry_size;		/* size of one entry in bytes */
+	unsigned long	hdr_count;		/* how many valid entries */
+	unsigned long	hdr_pmds;		/* which pmds are recorded */
+} perfmon_smpl_hdr_t;
 
-#if 0
+/*
+ * Header entry in the buffer as a header as follows.
+ * The header is directly followed with the PMDS to saved in increasing index order:
+ * PMD4, PMD5, .... How many PMDs are present is determined by the tool which must
+ * keep track of it when generating the final trace file.
+ */
 typedef struct {
-	unsigned long pmu_reg_data;	/* generic PMD register */
-	unsigned long pmu_reg_num;	/* which register number */
-} perfmon_reg_t; 
-#endif
+	int		pid;		/* identification of process */
+	int		cpu;		/* which cpu was used */
+	unsigned long	rate;		/* initial value of this counter */
+	unsigned long	stamp;		/* timestamp */
+	unsigned long	ip;		/* where did the overflow interrupt happened */
+	unsigned long	regs;		/* which registers overflowed (up to 64)*/
+} perfmon_smpl_entry_t;
 
 /*
- * This structure is initialize at boot time and contains
+ * There is one such data structure per perfmon context. It is used to describe the
+ * sampling buffer. It is to be shared among siblings whereas the pfm_context isn't.
+ * Therefore we maintain a refcnt which is incremented on fork().
+ * This buffer is private to the kernel only the actual sampling buffer including its
+ * header are exposed to the user. This construct allows us to export the buffer read-write,
+ * if needed, without worrying about security problems.
+ */
+typedef struct {
+	atomic_t		psb_refcnt;	/* how many users for the buffer */
+	int			reserved;
+	void			*psb_addr;	/* points to location of first entry */
+	unsigned long		psb_entries;	/* maximum number of entries */
+	unsigned long		psb_size;	/* aligned size of buffer */
+	unsigned long		psb_index;	/* next free entry slot */
+	unsigned long		psb_entry_size;	/* size of each entry including entry header */
+	perfmon_smpl_hdr_t	*psb_hdr;	/* points to sampling buffer header */
+} pfm_smpl_buffer_desc_t;
+
+
+/*
+ * This structure is initialized at boot time and contains
  * a description of the PMU main characteristic as indicated
  * by PAL
  */
 typedef struct {
+	unsigned long pfm_is_disabled;	/* indicates if perfmon is working properly */
 	unsigned long perf_ovfl_val;	/* overflow value for generic counters   */
 	unsigned long max_counters;	/* upper limit on counter pair (PMC/PMD) */
+	unsigned long num_pmcs ;	/* highest PMC implemented (may have holes) */
+	unsigned long num_pmds;		/* highest PMD implemented (may have holes) */
 	unsigned long impl_regs[16];	/* buffer used to hold implememted PMC/PMD mask */
 } pmu_config_t;
 
+#define PERFMON_IS_DISABLED() pmu_conf.pfm_is_disabled
+
+typedef struct {
+	__u64		val;		/* virtual 64bit counter value */
+	__u64		ival;		/* initial value from user */
+	__u64		smpl_rval;	/* reset value on sampling overflow */
+	__u64		ovfl_rval;	/* reset value on overflow */
+	int		flags;		/* notify/do not notify */
+} pfm_counter_t;
+#define PMD_OVFL_NOTIFY(ctx, i)	((ctx)->ctx_pmds[i].flags &  PFM_REGFL_OVFL_NOTIFY)
+
+/*
+ * perfmon context. One per process, is cloned on fork() depending on inheritance flags
+ */
+typedef struct {
+	unsigned int inherit:2;	/* inherit mode */
+	unsigned int noblock:1;	/* block/don't block on overflow with notification */
+	unsigned int system:1;	/* do system wide monitoring */
+	unsigned int frozen:1;	/* pmu must be kept frozen on ctxsw in */
+	unsigned int reserved:27;
+} pfm_context_flags_t;
+
+typedef struct pfm_context {
+
+	pfm_smpl_buffer_desc_t	*ctx_smpl_buf;		/* sampling buffer descriptor, if any */
+	unsigned long		ctx_dear_counter;	/* which PMD holds D-EAR */
+	unsigned long		ctx_iear_counter;	/* which PMD holds I-EAR */
+	unsigned long		ctx_btb_counter;	/* which PMD holds BTB */
+
+	pid_t			ctx_notify_pid;	/* who to notify on overflow */
+	int			ctx_notify_sig;	/* XXX: SIGPROF or other */
+	pfm_context_flags_t	ctx_flags;	/* block/noblock */
+	pid_t			ctx_creator;	/* pid of creator (debug) */
+	unsigned long		ctx_ovfl_regs;	/* which registers just overflowed (notification) */
+	unsigned long		ctx_smpl_regs;	/* which registers to record on overflow */
+
+	struct semaphore	ctx_restart_sem; /* use for blocking notification mode */
+
+	pfm_counter_t		ctx_pmds[IA64_NUM_PMD_COUNTERS]; /* XXX: size should be dynamic */
+} pfm_context_t;
+
+#define ctx_fl_inherit	ctx_flags.inherit
+#define ctx_fl_noblock	ctx_flags.noblock
+#define ctx_fl_system	ctx_flags.system
+#define ctx_fl_frozen	ctx_flags.frozen
+
+#define CTX_IS_DEAR(c,n)	((c)->ctx_dear_counter == (n))
+#define CTX_IS_IEAR(c,n)	((c)->ctx_iear_counter == (n))
+#define CTX_IS_BTB(c,n)		((c)->ctx_btb_counter == (n))
+#define CTX_OVFL_NOBLOCK(c)	((c)->ctx_fl_noblock == 1)
+#define CTX_INHERIT_MODE(c)	((c)->ctx_fl_inherit)
+#define CTX_HAS_SMPL(c)		((c)->ctx_smpl_buf != NULL)
+
 static pmu_config_t pmu_conf;
 
 /* for debug only */
-static unsigned long pfm_debug=1;	/* 0= nodebug, >0= debug output on */
-#define DBprintk(a)	{\
-	if (pfm_debug >0) { printk a; } \
+static unsigned long pfm_debug=0;	/* 0= nodebug, >0= debug output on */
+#define DBprintk(a) \
+	do { \
+		if (pfm_debug >0) { printk(__FUNCTION__" "); printk a; } \
+	} while (0);
+
+static void perfmon_softint(unsigned long ignored);
+static void ia64_reset_pmu(void);
+
+DECLARE_TASKLET(pfm_tasklet, perfmon_softint, 0);
+
+/*
+ * structure used to pass information between the interrupt handler
+ * and the tasklet.
+ */
+typedef struct {
+	pid_t		to_pid;		/* which process to notify */
+	pid_t		from_pid;	/* which process is source of overflow */
+	int		sig;		/* with which signal */
+	unsigned long	bitvect;	/* which counters have overflowed */
+} notification_info_t;
+
+#define notification_is_invalid(i)	(i->to_pid < 2)
+
+/* will need to be cache line padded */
+static notification_info_t notify_info[NR_CPUS];
+
+/*
+ * We force cache line alignment to avoid false sharing
+ * given that we have one entry per CPU.
+ */
+static struct {
+	struct task_struct *owner;
+} ____cacheline_aligned pmu_owners[NR_CPUS];
+/* helper macros */
+#define SET_PMU_OWNER(t)	do { pmu_owners[smp_processor_id()].owner = (t); } while(0);
+#define PMU_OWNER()		pmu_owners[smp_processor_id()].owner
+
+/* for debug only */
+static struct proc_dir_entry *perfmon_dir;
+
+/*
+ * finds the number of PM(C|D) registers given
+ * the bitvector returned by PAL
+ */
+static unsigned long __init
+find_num_pm_regs(long *buffer)
+{
+	int i=3; /* 4 words/per bitvector */
+
+	/* start from the most significant word */
+	while (i>=0 && buffer[i] == 0 ) i--;
+	if (i< 0) {
+		printk(KERN_ERR "perfmon: No bit set in pm_buffer\n");
+		return 0;
+	}
+	return 1+ ia64_fls(buffer[i]) + 64 * i;
 }
 
+
 /*
- * could optimize to avoid cache line conflicts in SMP
+ * Generates a unique (per CPU) timestamp
+ */
+static inline unsigned long
+perfmon_get_stamp(void)
+{
+	/*
+	 * XXX: maybe find something more efficient
+	 */
+	return ia64_get_itc();
+}
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
  */
-static struct task_struct *pmu_owners[NR_CPUS];
+static inline unsigned long
+uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+	unsigned long ret = 0UL;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	if (!pgd_none(*pgd)) {
+		pmd = pmd_offset(pgd, adr);
+		if (!pmd_none(*pmd)) {
+			ptep = pte_offset(pmd, adr);
+			pte = *ptep;
+			if (pte_present(pte)) {
+				ret = (unsigned long) page_address(pte_page(pte));
+				ret |= (adr & (PAGE_SIZE - 1));
+			}
+		}
+	}
+	DBprintk(("uv2kva(%lx-->%lx)\n", adr, ret));
+	return ret;
+}
+
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long
+kvirt_to_pa(unsigned long adr)
+{
+	__u64 pa;
+	__asm__ __volatile__ ("tpa %0 = %1" : "=r"(pa) : "r"(adr) : "memory");
+	DBprintk(("kv2pa(%lx-->%lx)\n", adr, pa));
+	return pa;
+}
+
+static void *
+rvmalloc(unsigned long size)
+{
+	void *mem;
+	unsigned long adr, page;
+
+	/* XXX: may have to revisit this part because
+	 * vmalloc() does not necessarily return a page-aligned buffer.
+	 * This maybe a security problem when mapped at user level
+	 */
+	mem=vmalloc(size);
+	if (mem) {
+		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+		adr=(unsigned long) mem;
+		while (size > 0) {
+			page = kvirt_to_pa(adr);
+			mem_map_reserve(virt_to_page(__va(page)));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+	}
+	return mem;
+}
+
+static void
+rvfree(void *mem, unsigned long size)
+{
+	unsigned long adr, page;
+
+	if (mem) {
+		adr=(unsigned long) mem;
+		while (size > 0) {
+			page = kvirt_to_pa(adr);
+			mem_map_unreserve(virt_to_page(__va(page)));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+		vfree(mem);
+	}
+}
+
+static pfm_context_t *
+pfm_context_alloc(void)
+{
+	pfm_context_t *pfc;
+
+	/* allocate context descriptor */
+	pfc = vmalloc(sizeof(*pfc));
+	if (pfc) memset(pfc, 0, sizeof(*pfc));
+
+	return pfc;
+}
+
+static void
+pfm_context_free(pfm_context_t *pfc)
+{
+	if (pfc) vfree(pfc);
+}
 
 static int
-do_perfmonctl (struct task_struct *task, int cmd, int flags, perfmon_req_t *req, int count, struct pt_regs *regs)
+pfm_remap_buffer(unsigned long buf, unsigned long addr, unsigned long size)
 {
-        perfmon_req_t tmp;
-        int i;
+	unsigned long page;
 
-        switch (cmd) {
-		case PFM_WRITE_PMCS:          
-			/* we don't quite support this right now */
-			if (task != current) return -EINVAL;
+	while (size > 0) {
+		page = kvirt_to_pa(buf);
 
-			if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
+		if (remap_page_range(addr, page, PAGE_SIZE, PAGE_SHARED)) return -ENOMEM;
+
+		addr  += PAGE_SIZE;
+		buf   += PAGE_SIZE;
+		size  -= PAGE_SIZE;
+	}
+	return 0;
+}
+
+/*
+ * counts the number of PMDS to save per entry.
+ * This code is generic enough to accomodate more than 64 PMDS when they become available
+ */
+static unsigned long
+pfm_smpl_entry_size(unsigned long *which, unsigned long size)
+{
+	unsigned long res = 0;
+	int i;
+
+	for (i=0; i < size; i++, which++) res += hweight64(*which);
+
+	DBprintk((" res=%ld\n", res));
+
+	return res;
+}
+
+/*
+ * Allocates the sampling buffer and remaps it into caller's address space
+ */
+static int
+pfm_smpl_buffer_alloc(pfm_context_t *ctx, unsigned long which_pmds, unsigned long entries, void **user_addr)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long addr, size, regcount;
+	void *smpl_buf;
+	pfm_smpl_buffer_desc_t *psb;
+
+	regcount = pfm_smpl_entry_size(&which_pmds, 1);
+
+	/* note that regcount might be 0, in this case only the header for each
+	 * entry will be recorded.
+	 */
+
+	/*
+	 * 1 buffer hdr and for each entry a header + regcount PMDs to save
+	 */
+	size = PAGE_ALIGN(  sizeof(perfmon_smpl_hdr_t)
+			  + entries * (sizeof(perfmon_smpl_entry_t) + regcount*sizeof(u64)));
+	/*
+	 * check requested size to avoid Denial-of-service attacks
+	 * XXX: may have to refine this test
+	 */
+	if (size > current->rlim[RLIMIT_MEMLOCK].rlim_cur) return -EAGAIN;
+
+	/* find some free area in address space */
+	addr = get_unmapped_area(NULL, 0, size, 0, 0);
+	if (!addr) goto no_addr;
+
+	DBprintk((" entries=%ld aligned size=%ld, unmapped @0x%lx\n", entries, size, addr));
+
+	/* allocate vma */
+	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+	if (!vma) goto no_vma;
+
+	/* XXX: see rvmalloc() for page alignment problem */
+	smpl_buf = rvmalloc(size);
+	if (smpl_buf == NULL) goto no_buffer;
+
+	DBprintk((" smpl_buf @%p\n", smpl_buf));
+
+	if (pfm_remap_buffer((unsigned long)smpl_buf, addr, size)) goto cant_remap;
+
+	/* allocate sampling buffer descriptor now */
+	psb = vmalloc(sizeof(*psb));
+	if (psb == NULL) goto no_buffer_desc;
+
+	/* start with something clean */
+	memset(smpl_buf, 0x0, size);
+
+	psb->psb_hdr	 = smpl_buf;
+	psb->psb_addr    = (char *)smpl_buf+sizeof(perfmon_smpl_hdr_t); /* first entry */
+	psb->psb_size    = size; /* aligned size */
+	psb->psb_index   = 0;
+	psb->psb_entries = entries;
+
+	atomic_set(&psb->psb_refcnt, 1);
+
+	psb->psb_entry_size = sizeof(perfmon_smpl_entry_t) + regcount*sizeof(u64);
+
+	DBprintk((" psb @%p entry_size=%ld hdr=%p addr=%p\n", (void *)psb,psb->psb_entry_size, (void *)psb->psb_hdr, (void *)psb->psb_addr));
+
+	/* initialize some of the fields of header */
+	psb->psb_hdr->hdr_version    = PFM_SMPL_HDR_VERSION;
+	psb->psb_hdr->hdr_entry_size = sizeof(perfmon_smpl_entry_t)+regcount*sizeof(u64);
+	psb->psb_hdr->hdr_pmds	     = which_pmds;
+
+	/* store which PMDS to record */
+	ctx->ctx_smpl_regs = which_pmds;
+
+	/* link to perfmon context */
+	ctx->ctx_smpl_buf  = psb;
+
+	/*
+	 * initialize the vma for the sampling buffer
+	 */
+	vma->vm_mm	  = mm;
+	vma->vm_start	  = addr;
+	vma->vm_end	  = addr + size;
+	vma->vm_flags	  = VM_READ|VM_MAYREAD;
+	vma->vm_page_prot = PAGE_READONLY; /* XXX may need to change */
+	vma->vm_ops	  = NULL;
+	vma->vm_pgoff	  = 0;
+	vma->vm_file	  = NULL;
+	vma->vm_raend	  = 0;
+
+	vma->vm_private_data = ctx;	/* link to pfm_context(not yet used) */
+
+	/*
+	 * now insert the vma in the vm list for the process
+	 */
+	insert_vm_struct(mm, vma);
+
+	mm->total_vm  += size >> PAGE_SHIFT;
+
+	/*
+	 * that's the address returned to the user
+	 */
+	*user_addr = (void *)addr;
+
+	return 0;
+
+	/* outlined error handling */
+no_addr:
+	DBprintk(("Cannot find unmapped area for size %ld\n", size));
+	return -ENOMEM;
+no_vma:
+	DBprintk(("Cannot allocate vma\n"));
+	return -ENOMEM;
+cant_remap:
+	DBprintk(("Can't remap buffer\n"));
+	rvfree(smpl_buf, size);
+no_buffer:
+	DBprintk(("Can't allocate sampling buffer\n"));
+	kmem_cache_free(vm_area_cachep, vma);
+	return -ENOMEM;
+no_buffer_desc:
+	DBprintk(("Can't allocate sampling buffer descriptor\n"));
+	kmem_cache_free(vm_area_cachep, vma);
+	rvfree(smpl_buf, size);
+	return -ENOMEM;
+}
+
+static int
+pfx_is_sane(pfreq_context_t *pfx)
+{
+	/* valid signal */
+	if (pfx->notify_sig < 1 || pfx->notify_sig >= _NSIG) return 0;
+
+	/* cannot send to process 1, 0 means do not notify */
+	if (pfx->notify_pid < 0 || pfx->notify_pid == 1) return 0;
+
+	/* asked for sampling, but nothing to record ! */
+	if (pfx->smpl_entries > 0 && pfm_smpl_entry_size(&pfx->smpl_regs, 1) == 0) return 0;
+
+	/* probably more to add here */
+
+
+	return 1;
+}
+
+static int
+pfm_context_create(struct task_struct *task, int flags, perfmon_req_t *req)
+{
+	pfm_context_t *ctx;
+	perfmon_req_t tmp;
+	void *uaddr = NULL;
+	int ret = -EFAULT;
+	int ctx_flags;
+
+	/* to go away */
+	if (flags) {
+		printk("perfmon: use context flags instead of perfmon() flags. Obsoleted API\n");
+	}
+
+	if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
+
+	ctx_flags = tmp.pfr_ctx.flags;
+
+	/* not yet supported */
+	if (ctx_flags & PFM_FL_SYSTEMWIDE) return -EINVAL;
+
+	if (!pfx_is_sane(&tmp.pfr_ctx)) return -EINVAL;
+
+	ctx = pfm_context_alloc();
+	if (!ctx) return -ENOMEM;
+
+	/* record who the creator is (for debug) */
+	ctx->ctx_creator = task->pid;
+
+	ctx->ctx_notify_pid = tmp.pfr_ctx.notify_pid;
+	ctx->ctx_notify_sig = SIGPROF;	/* siginfo imposes a fixed signal */
+
+	if (tmp.pfr_ctx.smpl_entries) {
+		DBprintk((" sampling entries=%ld\n",tmp.pfr_ctx.smpl_entries));
+		if ((ret=pfm_smpl_buffer_alloc(ctx, tmp.pfr_ctx.smpl_regs, tmp.pfr_ctx.smpl_entries, &uaddr)) ) goto buffer_error;
+		tmp.pfr_ctx.smpl_vaddr = uaddr;
+	}
+	/* initialization of context's flags */
+	ctx->ctx_fl_inherit = ctx_flags & PFM_FL_INHERIT_MASK;
+	ctx->ctx_fl_noblock = (ctx_flags & PFM_FL_SMPL_OVFL_NOBLOCK) ? 1 : 0;
+	ctx->ctx_fl_system  = (ctx_flags & PFM_FL_SYSTEMWIDE) ? 1: 0;
+	ctx->ctx_fl_frozen  = 0;
+
+	sema_init(&ctx->ctx_restart_sem, 0); /* init this semaphore to locked */
+
+	if (copy_to_user(req, &tmp, sizeof(tmp))) goto buffer_error;
+
+	DBprintk((" context=%p, pid=%d notify_sig %d notify_pid=%d\n",(void *)ctx, task->pid, ctx->ctx_notify_sig, ctx->ctx_notify_pid));
+	DBprintk((" context=%p, pid=%d flags=0x%x inherit=%d noblock=%d system=%d\n",(void *)ctx, task->pid, ctx_flags, ctx->ctx_fl_inherit, ctx->ctx_fl_noblock, ctx->ctx_fl_system));
+
+	/* link with task */
+	task->thread.pfm_context = ctx;
+
+	return 0;
+
+buffer_error:
+	vfree(ctx);
+
+	return ret;
+}
+
+static void
+pfm_reset_regs(pfm_context_t *ctx)
+{
+	unsigned long mask = ctx->ctx_ovfl_regs;
+	int i, cnum;
+
+	DBprintk((" ovfl_regs=0x%lx\n", mask));
+	/*
+	 * now restore reset value on sampling overflowed counters
+	 */
+	for(i=0, cnum=PMU_FIRST_COUNTER; i < pmu_conf.max_counters; i++, cnum++, mask >>= 1) {
+		if (mask & 0x1) {
+			DBprintk((" reseting PMD[%d]=%lx\n", cnum, ctx->ctx_pmds[i].smpl_rval & pmu_conf.perf_ovfl_val));
+
+			/* upper part is ignored on rval */
+			ia64_set_pmd(cnum, ctx->ctx_pmds[i].smpl_rval);
+		}
+	}
+}
+
+static int
+pfm_write_pmcs(struct task_struct *ta, perfmon_req_t *req, int count)
+{
+	struct thread_struct *th = &ta->thread;
+	pfm_context_t *ctx = th->pfm_context;
+	perfmon_req_t tmp;
+	unsigned long cnum;
+	int i;
+
+	/* XXX: ctx locking may be required here */
+
+	for (i = 0; i < count; i++, req++) {
+
+		if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
+
+		cnum = tmp.pfr_reg.reg_num;
+
+		/* XXX needs to check validity of the data maybe */
+		if (!PMC_IS_IMPL(cnum)) {
+			DBprintk((" invalid pmc[%ld]\n", cnum));
+			return -EINVAL;
+		}
+
+		if (PMC_IS_COUNTER(cnum)) {
+
+			/*
+			 * we keep track of EARS/BTB to speed up sampling later
+			 */
+			if (PMC_IS_DEAR(&tmp.pfr_reg.reg_value)) {
+				ctx->ctx_dear_counter = cnum;
+			} else if (PMC_IS_IEAR(&tmp.pfr_reg.reg_value)) {
+				ctx->ctx_iear_counter = cnum;
+			} else if (PMC_IS_BTB(&tmp.pfr_reg.reg_value)) {
+				ctx->ctx_btb_counter = cnum;
+			}
+
+			if (tmp.pfr_reg.reg_flags & PFM_REGFL_OVFL_NOTIFY)
+				ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags |= PFM_REGFL_OVFL_NOTIFY;
+		}
+
+		ia64_set_pmc(cnum, tmp.pfr_reg.reg_value);
+			DBprintk((" setting PMC[%ld]=0x%lx flags=0x%x\n", cnum, tmp.pfr_reg.reg_value, ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags));
+
+	}
+	/*
+	 * we have to set this here event hough we haven't necessarily started monitoring
+	 * because we may be context switched out
+	 */
+	th->flags |= IA64_THREAD_PM_VALID;
+
+	return 0;
+}
+
+static int
+pfm_write_pmds(struct task_struct *ta, perfmon_req_t *req, int count)
+{
+	struct thread_struct *th = &ta->thread;
+	pfm_context_t *ctx = th->pfm_context;
+	perfmon_req_t tmp;
+	unsigned long cnum;
+	int i;
+
+	/* XXX: ctx locking may be required here */
+
+	for (i = 0; i < count; i++, req++) {
+		int k;
+
+		if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
 
-			for (i = 0; i < count; i++, req++) {
-				copy_from_user(&tmp, req, sizeof(tmp));
+		cnum = tmp.pfr_reg.reg_num;
 
-				/* XXX needs to check validity of the data maybe */
+		k = cnum - PMU_FIRST_COUNTER;
 
-				if (!PMC_IS_IMPL(tmp.pfr_reg_num)) {
-					DBprintk((__FUNCTION__ " invalid pmc[%ld]\n", tmp.pfr_reg_num));
-					return -EINVAL;
-				}
-
-				/* XXX: for counters, need to some checks */
-				if (PMC_IS_COUNTER(tmp.pfr_reg_num)) {
-					current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].sig = tmp.pfr_notify_sig;
-					current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].pid = tmp.pfr_notify_pid;
-
-					DBprintk((__FUNCTION__" setting PMC[%ld] send sig %d to %d\n",tmp.pfr_reg_num, tmp.pfr_notify_sig, tmp.pfr_notify_pid));
-				}
-				ia64_set_pmc(tmp.pfr_reg_num, tmp.pfr_reg_value);
+		if (!PMD_IS_IMPL(cnum)) return -EINVAL;
 
-				DBprintk((__FUNCTION__" setting PMC[%ld]=0x%lx\n", tmp.pfr_reg_num, tmp.pfr_reg_value));
+		/* update virtualized (64bits) counter */
+		if (PMD_IS_COUNTER(cnum)) {
+			ctx->ctx_pmds[k].ival = tmp.pfr_reg.reg_value;
+			ctx->ctx_pmds[k].val  = tmp.pfr_reg.reg_value & ~pmu_conf.perf_ovfl_val;
+			ctx->ctx_pmds[k].smpl_rval = tmp.pfr_reg.reg_smpl_reset;
+			ctx->ctx_pmds[k].ovfl_rval = tmp.pfr_reg.reg_ovfl_reset;
+		}
+
+		/* writes to unimplemented part is ignored, so this is safe */
+		ia64_set_pmd(cnum, tmp.pfr_reg.reg_value);
+
+		/* to go away */
+		ia64_srlz_d();
+		DBprintk((" setting PMD[%ld]:  pmd.val=0x%lx pmd.ovfl_rval=0x%lx pmd.smpl_rval=0x%lx pmd=%lx\n",
+					cnum,
+					ctx->ctx_pmds[k].val,
+					ctx->ctx_pmds[k].ovfl_rval,
+					ctx->ctx_pmds[k].smpl_rval,
+					ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val));
+	}
+	/*
+	 * we have to set this here event hough we haven't necessarily started monitoring
+	 * because we may be context switched out
+	 */
+	th->flags |= IA64_THREAD_PM_VALID;
+
+	return 0;
+}
+
+static int
+pfm_read_pmds(struct task_struct *ta, perfmon_req_t *req, int count)
+{
+	struct thread_struct *th = &ta->thread;
+	pfm_context_t *ctx = th->pfm_context;
+	unsigned long val=0;
+	perfmon_req_t tmp;
+	int i;
+
+	/*
+	 * XXX: MUST MAKE SURE WE DON"T HAVE ANY PENDING OVERFLOW BEFORE READING
+	 * This is required when the monitoring has been stoppped by user of kernel.
+	 * If ity is still going on, then that's fine because we a re not gauranteed
+	 * to return an accurate value in this case
+	 */
+
+	/* XXX: ctx locking may be required here */
+
+	for (i = 0; i < count; i++, req++) {
+		int k;
+
+		if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
+
+		if (!PMD_IS_IMPL(tmp.pfr_reg.reg_num)) return -EINVAL;
+
+		k = tmp.pfr_reg.reg_num - PMU_FIRST_COUNTER;
+
+		if (PMD_IS_COUNTER(tmp.pfr_reg.reg_num)) {
+			if (ta == current){
+				val = ia64_get_pmd(tmp.pfr_reg.reg_num);
+			} else {
+				val = th->pmd[k];
 			}
+			val &= pmu_conf.perf_ovfl_val;
 			/*
-			 * we have to set this here event hough we haven't necessarily started monitoring
-			 * because we may be context switched out
+			 * lower part of .val may not be zero, so we must be an addition because of
+			 * residual count (see update_counters).
 			 */
-			current->thread.flags |= IA64_THREAD_PM_VALID;
-                	break;
+			val += ctx->ctx_pmds[k].val;
+		} else {
+			/* for now */
+			if (ta != current) return -EINVAL;
 
-		case PFM_WRITE_PMDS:
+			val = ia64_get_pmd(tmp.pfr_reg.reg_num);
+		}
+		tmp.pfr_reg.reg_value = val;
+
+		DBprintk((" reading PMD[%ld]=0x%lx\n", tmp.pfr_reg.reg_num, val));
+
+		if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
+	}
+	return 0;
+}
+
+static int
+pfm_do_restart(struct task_struct *task)
+{
+	struct thread_struct *th = &task->thread;
+	pfm_context_t *ctx = th->pfm_context;
+	void *sem = &ctx->ctx_restart_sem;
+
+	if (task == current) {
+		DBprintk((" restartig self %d frozen=%d \n", current->pid, ctx->ctx_fl_frozen));
+
+		pfm_reset_regs(ctx);
+
+		/*
+		 * We ignore block/don't block because we never block
+		 * for a self-monitoring process.
+		 */
+		ctx->ctx_fl_frozen = 0;
+
+		if (CTX_HAS_SMPL(ctx)) {
+			ctx->ctx_smpl_buf->psb_hdr->hdr_count = 0;
+			ctx->ctx_smpl_buf->psb_index = 0;
+		}
+
+		/* pfm_reset_smpl_buffers(ctx,th->pfm_ovfl_regs);*/
+
+		/* simply unfreeze */
+		ia64_set_pmc(0, 0);
+		ia64_srlz_d();
+
+		return 0;
+	}
+
+	/* check if blocking */
+	if (CTX_OVFL_NOBLOCK(ctx) == 0) {
+		DBprintk((" unblocking %d \n", task->pid));
+		up(sem);
+		return 0;
+	}
+
+	/*
+	 * in case of non blocking mode, then it's just a matter of
+	 * of reseting the sampling buffer (if any) index. The PMU
+	 * is already active.
+	 */
+
+	/*
+	 * must reset the header count first
+	 */
+	if (CTX_HAS_SMPL(ctx)) {
+		DBprintk((" resetting sampling indexes for %d \n", task->pid));
+		ctx->ctx_smpl_buf->psb_hdr->hdr_count = 0;
+		ctx->ctx_smpl_buf->psb_index = 0;
+	}
+
+	return 0;
+}
+
+
+static int
+do_perfmonctl (struct task_struct *task, int cmd, int flags, perfmon_req_t *req, int count, struct pt_regs *regs)
+{
+	perfmon_req_t tmp;
+	struct thread_struct *th = &task->thread;
+	pfm_context_t *ctx = th->pfm_context;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	switch (cmd) {
+		case PFM_CREATE_CONTEXT:
+			/* a context has already been defined */
+			if (ctx) return -EBUSY;
+
+			/* may be a temporary limitation */
+			if (task != current) return -EINVAL;
+
+			if (req == NULL || count != 1) return -EINVAL;
+
+			if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
+
+			return pfm_context_create(task, flags, req);
+
+		case PFM_WRITE_PMCS:
 			/* we don't quite support this right now */
 			if (task != current) return -EINVAL;
 
 			if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
 
-			for (i = 0; i < count; i++, req++) {
-				copy_from_user(&tmp, req, sizeof(tmp));
+			if (!ctx) {
+				DBprintk((" PFM_WRITE_PMCS: no context for task %d\n", task->pid));
+				return -EINVAL;
+			}
+			return pfm_write_pmcs(task, req, count);
+
+		case PFM_WRITE_PMDS:
+			/* we don't quite support this right now */
+			if (task != current) return -EINVAL;
 
-				if (!PMD_IS_IMPL(tmp.pfr_reg_num)) return -EINVAL;
+			if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
 
-				/* update virtualized (64bits) counter */
-				if (PMD_IS_COUNTER(tmp.pfr_reg_num)) {
-					current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].val  = tmp.pfr_reg_value & ~pmu_conf.perf_ovfl_val;
-					current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].rval = tmp.pfr_reg_reset;
-				}
-				/* writes to unimplemented part is ignored, so this is safe */
-				ia64_set_pmd(tmp.pfr_reg_num, tmp.pfr_reg_value);
-				/* to go away */
-				ia64_srlz_d();
-				DBprintk((__FUNCTION__" setting PMD[%ld]:  pmod.val=0x%lx pmd=0x%lx rval=0x%lx\n", tmp.pfr_reg_num, current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].val, ia64_get_pmd(tmp.pfr_reg_num),current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].rval));
+			if (!ctx) {
+				DBprintk((" PFM_WRITE_PMDS: no context for task %d\n", task->pid));
+				return -EINVAL;
 			}
-			/*
-			 * we have to set this here event hough we haven't necessarily started monitoring
-			 * because we may be context switched out
-			 */
-			current->thread.flags |= IA64_THREAD_PM_VALID;
-                	break;
+			return pfm_write_pmds(task, req, count);
 
 		case PFM_START:
 			/* we don't quite support this right now */
 			if (task != current) return -EINVAL;
 
-			pmu_owners[smp_processor_id()] = current;
+			if (!ctx) {
+				DBprintk((" PFM_START: no context for task %d\n", task->pid));
+				return -EINVAL;
+			}
+
+			SET_PMU_OWNER(current);
 
 			/* will start monitoring right after rfi */
 			ia64_psr(regs)->up = 1;
 
-			/* 
-		 	 * mark the state as valid.
-		 	 * this will trigger save/restore at context switch
-		 	 */
-			current->thread.flags |= IA64_THREAD_PM_VALID;
+			/*
+			 * mark the state as valid.
+			 * this will trigger save/restore at context switch
+			 */
+			th->flags |= IA64_THREAD_PM_VALID;
 
 			ia64_set_pmc(0, 0);
+			ia64_srlz_d();
 
-                	break;
+		break;
 
 		case PFM_ENABLE:
 			/* we don't quite support this right now */
 			if (task != current) return -EINVAL;
 
-			pmu_owners[smp_processor_id()] = current;
+			if (!ctx) {
+				DBprintk((" PFM_ENABLE: no context for task %d\n", task->pid));
+				return -EINVAL;
+			}
+
+			/* reset all registers to stable quiet state */
+			ia64_reset_pmu();
+
+			/* make sure nothing starts */
+			ia64_psr(regs)->up = 0;
+			ia64_psr(regs)->pp = 0;
+
+			/* do it on the live register as well */
+			__asm__ __volatile__ ("rsm psr.pp|psr.pp;;"::: "memory");
+
+			SET_PMU_OWNER(current);
 
-			/* 
-		 	 * mark the state as valid.
-		 	 * this will trigger save/restore at context switch
-		 	 */
-			current->thread.flags |= IA64_THREAD_PM_VALID;
+			/*
+			 * mark the state as valid.
+			 * this will trigger save/restore at context switch
+			 */
+			th->flags |= IA64_THREAD_PM_VALID;
 
 			/* simply unfreeze */
 			ia64_set_pmc(0, 0);
+			ia64_srlz_d();
 			break;
 
 		case PFM_DISABLE:
 			/* we don't quite support this right now */
 			if (task != current) return -EINVAL;
 
-			/* simply unfreeze */
+			/* simply freeze */
 			ia64_set_pmc(0, 1);
 			ia64_srlz_d();
 			break;
 
-	        case PFM_READ_PMDS:
+		case PFM_READ_PMDS:
 			if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
 			if (!access_ok(VERIFY_WRITE, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
 
-		/* This looks shady, but IMHO this will work fine. This is  
-		 * the sequence that I could come up with to avoid races
-		 * with the interrupt handler. See explanation in the 
-		 * following comment.
-		 */
-#if 0
-/* irrelevant with user monitors */
-		local_irq_save(flags);
-		__asm__ __volatile__("rsm psr.pp\n");
-		dcr = ia64_get_dcr();
-		dcr &= ~IA64_DCR_PP;
-		ia64_set_dcr(dcr);
-		local_irq_restore(flags);
-#endif
-		/*
-		 * We cannot write to pmc[0] to stop counting here, as
-		 * that particular instruction might cause an overflow
-		 * and the mask in pmc[0] might get lost. I'm _not_ 
-		 * sure of the hardware behavior here. So we stop
-		 * counting by psr.pp = 0. And we reset dcr.pp to
-		 * prevent an interrupt from mucking up psr.pp in the
-		 * meanwhile. Perfmon interrupts are pended, hence the
-		 * above code should be ok if one of the above instructions 
-		 * caused overflows, i.e the interrupt should get serviced
-		 * when we re-enabled interrupts. When I muck with dcr, 
-		 * is the irq_save/restore needed?
-		 */
-
-		for (i = 0; i < count; i++, req++) {
-			unsigned long val=0;
-
-			copy_from_user(&tmp, req, sizeof(tmp));
-
-			if (!PMD_IS_IMPL(tmp.pfr_reg_num)) return -EINVAL;
-
-			if (PMD_IS_COUNTER(tmp.pfr_reg_num)) {
-				if (task == current){
-					val = ia64_get_pmd(tmp.pfr_reg_num) & pmu_conf.perf_ovfl_val;
-				} else {
-					val = task->thread.pmd[tmp.pfr_reg_num - PMU_FIRST_COUNTER] & pmu_conf.perf_ovfl_val;
-				}
-				val += task->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].val;
-			} else {
-				/* for now */
-				if (task != current) return -EINVAL;
-
-				val = ia64_get_pmd(tmp.pfr_reg_num);
+			if (!ctx) {
+				DBprintk((" PFM_READ_PMDS: no context for task %d\n", task->pid));
+				return -EINVAL;
 			}
-			tmp.pfr_reg_value = val;
-
-DBprintk((__FUNCTION__" reading PMD[%ld]=0x%lx\n", tmp.pfr_reg_num, val));
-
-			if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
-		}
-#if 0
-/* irrelevant with user monitors */
-		local_irq_save(flags);
-		__asm__ __volatile__("ssm psr.pp");
-		dcr = ia64_get_dcr();
-		dcr |= IA64_DCR_PP;
-		ia64_set_dcr(dcr);
-		local_irq_restore(flags);
-#endif
-                break;
+			return pfm_read_pmds(task, req, count);
 
 	      case PFM_STOP:
-		/* we don't quite support this right now */
-		if (task != current) return -EINVAL;
+			/* we don't quite support this right now */
+			if (task != current) return -EINVAL;
 
-		ia64_set_pmc(0, 1);
-		ia64_srlz_d();
+			ia64_set_pmc(0, 1);
+			ia64_srlz_d();
 
-		ia64_psr(regs)->up = 0;
+			ia64_psr(regs)->up = 0;
 
-		current->thread.flags &= ~IA64_THREAD_PM_VALID;
+			th->flags &= ~IA64_THREAD_PM_VALID;
 
-		pmu_owners[smp_processor_id()] = NULL;
+			SET_PMU_OWNER(NULL);
 
-#if 0
-/* irrelevant with user monitors */
-		local_irq_save(flags);
-		dcr = ia64_get_dcr();
-		dcr &= ~IA64_DCR_PP;
-		ia64_set_dcr(dcr);
-		local_irq_restore(flags);
-		ia64_psr(regs)->up = 0;
-#endif
-
-		break;
+			/* we probably will need some more cleanup here */
+			break;
 
 	      case PFM_DEBUG_ON:
-			printk(__FUNCTION__" debuggin on\n");
+			printk(" debugging on\n");
 			pfm_debug = 1;
 			break;
 
 	      case PFM_DEBUG_OFF:
-			printk(__FUNCTION__" debuggin off\n");
+			printk(" debugging off\n");
 			pfm_debug = 0;
 			break;
 
+	      case PFM_RESTART: /* temporary, will most likely end up as a PFM_ENABLE */
+
+			if ((th->flags & IA64_THREAD_PM_VALID) == 0) {
+				printk(" PFM_RESTART not monitoring\n");
+				return -EINVAL;
+			}
+			if (!ctx) {
+				printk(" PFM_RESTART no ctx for %d\n", task->pid);
+				return -EINVAL;
+			}
+			if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_fl_frozen==0) {
+				printk("task %d without pmu_frozen set\n", task->pid);
+				return -EINVAL;
+			}
+
+			return pfm_do_restart(task); /* we only look at first entry */
+
 	      default:
-		DBprintk((__FUNCTION__" UNknown command 0x%x\n", cmd));
-		return -EINVAL;
-		break;
-        }
-        return 0;
+			DBprintk((" UNknown command 0x%x\n", cmd));
+			return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * XXX: do something better here
+ */
+static int
+perfmon_bad_permissions(struct task_struct *task)
+{
+	/* stolen from bad_signal() */
+	return (current->session != task->session)
+	    && (current->euid ^ task->suid) && (current->euid ^ task->uid)
+	    && (current->uid ^ task->suid) && (current->uid ^ task->uid);
 }
 
 asmlinkage int
@@ -361,8 +1069,16 @@
 {
 	struct pt_regs *regs = (struct pt_regs *) &stack;
 	struct task_struct *child = current;
-	int ret;
+	int ret = -ESRCH;
+
+	/* sanity check:
+	 *
+	 * ensures that we don't do bad things in case the OS
+	 * does not have enough storage to save/restore PMC/PMD
+	 */
+	if (PERFMON_IS_DISABLED()) return -ENOSYS;
 
+	/* XXX: pid interface is going away in favor of pfm context */
 	if (pid != current->pid) {
 		read_lock(&tasklist_lock);
 		{
@@ -370,37 +1086,245 @@
 			if (child)
 				get_task_struct(child);
 		}
-		if (!child) { 
-			read_unlock(&tasklist_lock);
-			return -ESRCH;
-		}
+
+		if (!child) goto abort_call;
+
+		ret = -EPERM;
+
+		if (perfmon_bad_permissions(child)) goto abort_call;
+
 		/*
 		 * XXX: need to do more checking here
 		 */
-		if (child->state != TASK_ZOMBIE) {
-			DBprintk((__FUNCTION__" warning process %d not in stable state %ld\n", pid, child->state));
+		if (child->state != TASK_ZOMBIE && child->state != TASK_STOPPED) {
+			DBprintk((" warning process %d not in stable state %ld\n", pid, child->state));
 		}
-	} 
+	}
 	ret = do_perfmonctl(child, cmd, flags, req, count, regs);
 
+abort_call:
 	if (child != current) read_unlock(&tasklist_lock);
 
 	return ret;
 }
 
 
-static inline int
-update_counters (u64 pmc0)
+/*
+ * This function is invoked on the exit path of the kernel. Therefore it must make sure
+ * it does does modify the caller's input registers (in0-in7) in case of entry by system call
+ * which can be restarted. That's why it's declared as a system call and all 8 possible args
+ * are declared even though not used.
+ */
+#if __GNUC__ >= 3
+void asmlinkage
+pfm_overflow_notify(void)
+#else
+void asmlinkage
+pfm_overflow_notify(u64 arg0, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
+#endif
 {
-	unsigned long mask, i, cnum;
-	struct thread_struct *th;
-	struct task_struct *ta;
+	struct task_struct *task;
+	struct thread_struct *th = &current->thread;
+	pfm_context_t *ctx = current->thread.pfm_context;
+	struct siginfo si;
+	int ret;
 
-	if (pmu_owners[smp_processor_id()] == NULL) {
-		DBprintk((__FUNCTION__" Spurious overflow interrupt: PMU not owned\n"));
-		return 0;
+	/*
+	 * do some sanity checks first
+	 */
+	if (!ctx) {
+		printk("perfmon: process %d has no PFM context\n", current->pid);
+		return;
+	}
+	if (ctx->ctx_notify_pid < 2) {
+		printk("perfmon: process %d invalid notify_pid=%d\n", current->pid, ctx->ctx_notify_pid);
+		return;
+	}
+
+	DBprintk((" current=%d ctx=%p bv=0%lx\n", current->pid, (void *)ctx, ctx->ctx_ovfl_regs));
+	/*
+	 * NO matter what notify_pid is,
+	 * we clear overflow, won't notify again
+	 */
+	th->pfm_pend_notify = 0;
+
+	/*
+	 * When measuring in kernel mode and non-blocking fashion, it is possible to
+	 * get an overflow while executing this code. Therefore the state of pend_notify
+	 * and ovfl_regs can be altered. The important point is not to loose any notification.
+	 * It is fine to get called for nothing. To make sure we do collect as much state as
+	 * possible, update_counters() always uses |= to add bit to the ovfl_regs field.
+	 *
+	 * In certain cases, it is possible to come here, with ovfl_regs == 0;
+	 *
+	 * XXX: pend_notify and ovfl_regs could be merged maybe !
+	 */
+	if (ctx->ctx_ovfl_regs == 0) {
+		printk("perfmon: spurious overflow notification from pid %d\n", current->pid);
+		return;
 	}
-	
+	read_lock(&tasklist_lock);
+
+	task = find_task_by_pid(ctx->ctx_notify_pid);
+
+	if (task) {
+		si.si_signo    = ctx->ctx_notify_sig;
+		si.si_errno    = 0;
+		si.si_code     = PROF_OVFL; /* goes to user */
+		si.si_addr     = NULL;
+		si.si_pid      = current->pid; /* who is sending */
+		si.si_pfm_ovfl = ctx->ctx_ovfl_regs;
+
+		DBprintk((" SIGPROF to %d @ %p\n", task->pid, (void *)task));
+
+		/* must be done with tasklist_lock locked */
+		ret = send_sig_info(ctx->ctx_notify_sig, &si, task);
+		if (ret != 0) {
+			DBprintk((" send_sig_info(process %d, SIGPROF)=%d\n", ctx->ctx_notify_pid, ret));
+			task = NULL; /* will cause return */
+		}
+	} else {
+		printk("perfmon: notify_pid %d not found\n", ctx->ctx_notify_pid);
+	}
+
+	read_unlock(&tasklist_lock);
+
+	/* now that we have released the lock handle error condition */
+	if (!task || CTX_OVFL_NOBLOCK(ctx)) {
+		/* we clear all pending overflow bits in noblock mode */
+		ctx->ctx_ovfl_regs = 0;
+		return;
+	}
+	DBprintk((" CPU%d %d before sleep\n", smp_processor_id(), current->pid));
+
+	/*
+	 * may go through without blocking on SMP systems
+	 * if restart has been received already by the time we call down()
+	 */
+	ret = down_interruptible(&ctx->ctx_restart_sem);
+
+	DBprintk((" CPU%d %d after sleep ret=%d\n", smp_processor_id(), current->pid, ret));
+
+	/*
+	 * in case of interruption of down() we don't restart anything
+	 */
+	if (ret >= 0) {
+		/* we reactivate on context switch */
+		ctx->ctx_fl_frozen = 0;
+		/*
+		 * the ovfl_sem is cleared by the restart task and this is safe because we always
+		 * use the local reference
+		 */
+
+		pfm_reset_regs(ctx);
+
+		/* now we can clear this mask */
+		ctx->ctx_ovfl_regs = 0;
+
+		/*
+		 * Unlock sampling buffer and reset index atomically
+		 * XXX: not really needed when blocking
+		 */
+		if (CTX_HAS_SMPL(ctx)) {
+			ctx->ctx_smpl_buf->psb_hdr->hdr_count = 0;
+			ctx->ctx_smpl_buf->psb_index = 0;
+		}
+
+		DBprintk((" CPU%d %d unfreeze PMU\n", smp_processor_id(), current->pid));
+
+		ia64_set_pmc(0, 0);
+		ia64_srlz_d();
+
+		/* state restored, can go back to work (user mode) */
+	}
+}
+
+static void
+perfmon_softint(unsigned long ignored)
+{
+	notification_info_t *info;
+	int my_cpu = smp_processor_id();
+	struct task_struct *task;
+	struct siginfo si;
+
+	info = notify_info+my_cpu;
+
+	DBprintk((" CPU%d current=%d to_pid=%d from_pid=%d bv=0x%lx\n", \
+		smp_processor_id(), current->pid, info->to_pid, info->from_pid, info->bitvect));
+
+	/* assumption check */
+	if (info->from_pid == info->to_pid) {
+		DBprintk((" Tasklet assumption error: from=%d tor=%d\n", info->from_pid, info->to_pid));
+		return;
+	}
+
+	if (notification_is_invalid(info)) {
+		DBprintk((" invalid notification information\n"));
+		return;
+	}
+
+	/* sanity check */
+	if (info->to_pid == 1) {
+		DBprintk((" cannot notify init\n"));
+		return;
+	}
+	/*
+	 * XXX: needs way more checks here to make sure we send to a task we have control over
+	 */
+	read_lock(&tasklist_lock);
+
+	task = find_task_by_pid(info->to_pid);
+
+	DBprintk((" after find %p\n", (void *)task));
+
+	if (task) {
+		int ret;
+
+		si.si_signo    = SIGPROF;
+		si.si_errno    = 0;
+		si.si_code     = PROF_OVFL; /* goes to user */
+		si.si_addr     =  NULL;
+		si.si_pid      = info->from_pid; /* who is sending */
+		si.si_pfm_ovfl = info->bitvect;
+
+		DBprintk((" SIGPROF to %d @ %p\n", task->pid, (void *)task));
+
+		/* must be done with tasklist_lock locked */
+		ret = send_sig_info(SIGPROF, &si, task);
+		if (ret != 0)
+			DBprintk((" send_sig_info(process %d, SIGPROF)=%d\n", info->to_pid, ret));
+
+		/* invalidate notification */
+		info->to_pid  = info->from_pid = 0;
+		info->bitvect = 0;
+	}
+
+	read_unlock(&tasklist_lock);
+
+	DBprintk((" after unlock %p\n", (void *)task));
+
+	if (!task) {
+		printk("perfmon: CPU%d cannot find process %d\n", smp_processor_id(), info->to_pid);
+	}
+}
+
+/*
+ * main overflow processing routine.
+ * it can be called from the interrupt path or explicitely during the context switch code
+ * Return:
+ *	0 : do not unfreeze the PMU
+ *	1 : PMU can be unfrozen
+ */
+static unsigned long
+update_counters (struct task_struct *ta, u64 pmc0, struct pt_regs *regs)
+{
+	unsigned long mask, i, cnum;
+	struct thread_struct *th;
+	pfm_context_t *ctx;
+	unsigned long bv = 0;
+	int my_cpu = smp_processor_id();
+	int ret = 1, buffer_is_full = 0;
+	int ovfl_is_smpl, can_notify, need_reset_pmd16=0;
 	/*
 	 * It is never safe to access the task for which the overflow interrupt is destinated
 	 * using the current variable as the interrupt may occur in the middle of a context switch
@@ -408,76 +1332,269 @@
 	 *
 	 * For monitoring, however, we do need to get access to the task which caused the overflow
 	 * to account for overflow on the counters.
+	 *
 	 * We accomplish this by maintaining a current owner of the PMU per CPU. During context
-	 * switch the ownership is changed in a way such that the reflected owner is always the 
+	 * switch the ownership is changed in a way such that the reflected owner is always the
 	 * valid one, i.e. the one that caused the interrupt.
 	 */
-	ta = pmu_owners[smp_processor_id()];
-	th = &pmu_owners[smp_processor_id()]->thread;
+
+	if (ta == NULL) {
+		DBprintk((" owners[%d]=NULL\n", my_cpu));
+		return 0x1;
+	}
+	th  = &ta->thread;
+	ctx = th->pfm_context;
 
 	/*
-	 * Don't think this could happen given first test. Keep as sanity check
+	 * XXX: debug test
+	 * Don't think this could happen given upfront tests
 	 */
 	if ((th->flags & IA64_THREAD_PM_VALID) == 0) {
-		DBprintk((__FUNCTION__" Spurious overflow interrupt: process %d not using perfmon\n", ta->pid));
+		printk("perfmon: Spurious overflow interrupt: process %d not using perfmon\n", ta->pid);
+		return 0x1;
+	}
+	if (!ctx) {
+		printk("perfmon: Spurious overflow interrupt: process %d has no PFM context\n", ta->pid);
 		return 0;
 	}
 
 	/*
-	 * if PMU not frozen: spurious from previous context 
-	 * if PMC[0] = 0x1 : frozen but no overflow reported: leftover from previous context
-	 *
-	 * in either case we don't touch the state upon return from handler
+	 * sanity test. Should never happen
 	 */
-	if ((pmc0 & 0x1) == 0 || pmc0 == 0x1) { 
-		DBprintk((__FUNCTION__" Spurious overflow interrupt: process %d freeze=0\n",ta->pid));
-		return 0;
+	if ((pmc0 & 0x1 )== 0) {
+		printk("perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n", ta->pid, pmc0);
+		return 0x0;
 	}
 
-	mask = pmc0 >> 4;
+	mask = pmc0 >> PMU_FIRST_COUNTER;
 
-	for (i = 0, cnum = PMU_FIRST_COUNTER; i < pmu_conf.max_counters; cnum++, i++, mask >>= 1) {
+	DBprintk(("pmc0=0x%lx pid=%d\n", pmc0, ta->pid));
 
-		if (mask & 0x1) {
-			DBprintk((__FUNCTION__ " PMD[%ld] overflowed pmd=0x%lx pmod.val=0x%lx\n", cnum, ia64_get_pmd(cnum), th->pmu_counters[i].val)); 
-			
+	DBprintk(("ctx is in %s mode\n", CTX_OVFL_NOBLOCK(ctx) ? "NO-BLOCK" : "BLOCK"));
+
+	if (CTX_HAS_SMPL(ctx)) {
+		pfm_smpl_buffer_desc_t *psb = ctx->ctx_smpl_buf;
+		unsigned long *e, m, idx=0;
+		perfmon_smpl_entry_t *h;
+		int j;
+
+		idx = ia64_fetch_and_add(1, &psb->psb_index);
+		DBprintk((" trying to record index=%ld entries=%ld\n", idx, psb->psb_entries));
+
+		/*
+		 * XXX: there is a small chance that we could run out on index before resetting
+		 * but index is unsigned long, so it will take some time.....
+		 */
+		if (idx > psb->psb_entries) {
+			buffer_is_full = 1;
+			goto reload_pmds;
+		}
+
+		/* first entry is really entry 0, not 1 caused by fetch_and_add */
+		idx--;
+
+		h = (perfmon_smpl_entry_t *)(((char *)psb->psb_addr) + idx*(psb->psb_entry_size));
+
+		h->pid  = ta->pid;
+		h->cpu  = my_cpu;
+		h->rate = 0;
+		h->ip   = regs ? regs->cr_iip : 0x0; /* where did the fault happened */
+		h->regs = mask; /* which registers overflowed */
+
+		/* guaranteed to monotonically increase on each cpu */
+		h->stamp = perfmon_get_stamp();
+
+		e = (unsigned long *)(h+1);
+		/*
+		 * selectively store PMDs in increasing index number
+		 */
+		for (j=0, m = ctx->ctx_smpl_regs; m; m >>=1, j++) {
+			if (m & 0x1) {
+				if (PMD_IS_COUNTER(j))
+					*e =  ctx->ctx_pmds[j-PMU_FIRST_COUNTER].val
+					    + (ia64_get_pmd(j) & pmu_conf.perf_ovfl_val);
+				else
+					*e = ia64_get_pmd(j); /* slow */
+				DBprintk((" e=%p pmd%d =0x%lx\n", (void *)e, j, *e));
+				e++;
+			}
+		}
+		/* make the new entry visible to user, needs to be atomic */
+		ia64_fetch_and_add(1, &psb->psb_hdr->hdr_count);
+
+		DBprintk((" index=%ld entries=%ld hdr_count=%ld\n", idx, psb->psb_entries, psb->psb_hdr->hdr_count));
+
+		/* sampling buffer full ? */
+		if (idx == (psb->psb_entries-1)) {
+			bv = mask;
+			buffer_is_full = 1;
+
+			DBprintk((" sampling buffer full must notify bv=0x%lx\n", bv));
+
+			if (!CTX_OVFL_NOBLOCK(ctx)) goto buffer_full;
 			/*
-			 * Because we somtimes (EARS/BTB) reset to a specific value, we cannot simply use 
-			 * val to count the number of times we overflowed. Otherwise we would loose the value
-			 * current in the PMD (which can be >0). So to make sure we don't loose
-			 * the residual counts we set val to contain full 64bits value of the counter.
+			 * here, we have a full buffer but we are in non-blocking mode
+			 * so we need to reloads overflowed PMDs with sampling reset values
+			 * and restart
 			 */
-			th->pmu_counters[i].val += 1+pmu_conf.perf_ovfl_val+(ia64_get_pmd(cnum) &pmu_conf.perf_ovfl_val);
+		}
+	}
+reload_pmds:
+	ovfl_is_smpl = CTX_OVFL_NOBLOCK(ctx) && buffer_is_full;
+	can_notify   = CTX_HAS_SMPL(ctx) == 0 && ctx->ctx_notify_pid;
 
-			/* writes to upper part are ignored, so this is safe */
-			ia64_set_pmd(cnum, th->pmu_counters[i].rval);
+	for (i = 0, cnum = PMU_FIRST_COUNTER; mask ; cnum++, i++, mask >>= 1) {
+
+		if ((mask & 0x1) == 0) continue;
+
+		DBprintk((" PMD[%ld] overflowed pmd=0x%lx pmod.val=0x%lx\n", cnum, ia64_get_pmd(cnum), ctx->ctx_pmds[i].val));
 
-			DBprintk((__FUNCTION__ " pmod[%ld].val=0x%lx pmd=0x%lx\n", i, th->pmu_counters[i].val, ia64_get_pmd(cnum)&pmu_conf.perf_ovfl_val)); 
+		/*
+		 * Because we sometimes (EARS/BTB) reset to a specific value, we cannot simply use
+		 * val to count the number of times we overflowed. Otherwise we would loose the current value
+		 * in the PMD (which can be >0). So to make sure we don't loose
+		 * the residual counts we set val to contain full 64bits value of the counter.
+		 *
+		 * XXX: is this needed for EARS/BTB ?
+		 */
+		ctx->ctx_pmds[i].val += 1 + pmu_conf.perf_ovfl_val
+				      + (ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val); /* slow */
+
+		DBprintk((" pmod[%ld].val=0x%lx pmd=0x%lx\n", i, ctx->ctx_pmds[i].val, ia64_get_pmd(cnum)&pmu_conf.perf_ovfl_val));
+
+		if (can_notify && PMD_OVFL_NOTIFY(ctx, i)) {
+			DBprintk((" CPU%d should notify process %d with signal %d\n", my_cpu, ctx->ctx_notify_pid, ctx->ctx_notify_sig));
+			bv |= 1 << i;
+		} else {
+			DBprintk((" CPU%d PMD[%ld] overflow, no notification\n", my_cpu, cnum));
+			/*
+			 * In case no notification is requested, we reload the reset value right away
+			 * otherwise we wait until the notify_pid process has been called and has
+			 * has finished processing data. Check out pfm_overflow_notify()
+			 */
 
-			if (th->pmu_counters[i].pid != 0 && th->pmu_counters[i].sig>0) {
-				DBprintk((__FUNCTION__ " shouild notify process %d with signal %d\n",th->pmu_counters[i].pid, th->pmu_counters[i].sig)); 
+			/* writes to upper part are ignored, so this is safe */
+			if (ovfl_is_smpl) {
+				DBprintk((" CPU%d PMD[%ld] reloaded with smpl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
+				ia64_set_pmd(cnum, ctx->ctx_pmds[i].smpl_rval);
+			} else {
+				DBprintk((" CPU%d PMD[%ld] reloaded with ovfl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
+				ia64_set_pmd(cnum, ctx->ctx_pmds[i].ovfl_rval);
 			}
 		}
+		if (cnum == ctx->ctx_btb_counter) need_reset_pmd16=1;
 	}
-	return 1;
+	/*
+	 * In case of BTB, overflow
+	 * we need to reset the BTB index.
+	 */
+	if (need_reset_pmd16) {
+		DBprintk(("reset PMD16\n"));
+		ia64_set_pmd(16, 0);
+	}
+buffer_full:
+	/* see pfm_overflow_notify() on details for why we use |= here */
+	ctx->ctx_ovfl_regs  |= bv;
+
+	/* nobody to notify, return and unfreeze */
+	if (!bv) return 0x0;
+
+
+	if (ctx->ctx_notify_pid == ta->pid) {
+		struct siginfo si;
+
+		si.si_errno    = 0;
+		si.si_addr     = NULL;
+		si.si_pid      = ta->pid; /* who is sending */
+
+
+		si.si_signo    = ctx->ctx_notify_sig; /* is SIGPROF */
+		si.si_code     = PROF_OVFL; /* goes to user */
+		si.si_pfm_ovfl = bv;
+
+
+		/*
+		 * in this case, we don't stop the task, we let it go on. It will
+		 * necessarily go to the signal handler (if any) when it goes back to
+		 * user mode.
+		 */
+		DBprintk((" sending %d notification to self %d\n", si.si_signo, ta->pid));
+
+
+		/* this call is safe in an interrupt handler */
+		ret = send_sig_info(ctx->ctx_notify_sig, &si, ta);
+		if (ret != 0)
+			printk(" send_sig_info(process %d, SIGPROF)=%d\n", ta->pid, ret);
+		/*
+		 * no matter if we block or not, we keep PMU frozen and do not unfreeze on ctxsw
+		 */
+		ctx->ctx_fl_frozen = 1;
+
+	} else {
+#if 0
+			/*
+			 * The tasklet is guaranteed to be scheduled for this CPU only
+			 */
+			notify_info[my_cpu].to_pid   = ctx->notify_pid;
+			notify_info[my_cpu].from_pid = ta->pid; /* for debug only */
+			notify_info[my_cpu].bitvect  = bv;
+			/* tasklet is inserted and active */
+			tasklet_schedule(&pfm_tasklet);
+#endif
+			/*
+			 * stored the vector of overflowed registers for use in notification
+			 * mark that a notification/blocking is pending (arm the trap)
+			 */
+		th->pfm_pend_notify = 1;
+
+		/*
+		 * if we do block, then keep PMU frozen until restart
+		 */
+		if (!CTX_OVFL_NOBLOCK(ctx)) ctx->ctx_fl_frozen = 1;
+
+		DBprintk((" process %d notify ovfl_regs=0x%lx\n", ta->pid, bv));
+	}
+	/*
+	 * keep PMU frozen (and overflowed bits cleared) when we have to stop,
+	 * otherwise return a resume 'value' for PMC[0]
+	 *
+	 * XXX: maybe that's enough to get rid of ctx_fl_frozen ?
+	 */
+	DBprintk((" will return pmc0=0x%x\n",ctx->ctx_fl_frozen ? 0x1 : 0x0));
+	return ctx->ctx_fl_frozen ? 0x1 : 0x0;
 }
 
 static void
 perfmon_interrupt (int irq, void *arg, struct pt_regs *regs)
 {
-	/* unfreeze if not spurious */
-	if ( update_counters(ia64_get_pmc(0)) ) {
-		ia64_set_pmc(0, 0);
+	u64 pmc0;
+	struct task_struct *ta;
+
+	pmc0 = ia64_get_pmc(0); /* slow */
+
+	/*
+	 * if we have some pending bits set
+	 * assumes : if any PM[0].bit[63-1] is set, then PMC[0].fr = 1
+	 */
+	if ((pmc0 & ~0x1) && (ta=PMU_OWNER())) {
+
+		/* assumes, PMC[0].fr = 1 at this point */
+		pmc0 = update_counters(ta, pmc0, regs);
+
+		/*
+		 * if pmu_frozen = 0
+		 *	pmc0 = 0 and we resume monitoring right away
+		 * else
+		 *	pmc0 = 0x1 frozen but all pending bits are cleared
+		 */
+		ia64_set_pmc(0, pmc0);
 		ia64_srlz_d();
+	} else {
+		printk("perfmon: Spurious PMU overflow interrupt: pmc0=0x%lx owner=%p\n", pmc0, (void *)PMU_OWNER());
 	}
 }
 
-static struct irqaction perfmon_irqaction = {
-	handler:	perfmon_interrupt,
-	flags:		SA_INTERRUPT,
-	name:		"perfmon"
-};
-
+/* for debug only */
 static int
 perfmon_proc_info(char *page)
 {
@@ -487,56 +1604,79 @@
 
 	p += sprintf(p, "PMC[0]=%lx\nPerfmon debug: %s\n", pmc0, pfm_debug ? "On" : "Off");
 	for(i=0; i < NR_CPUS; i++) {
-		if (cpu_is_online(i)) 
-			p += sprintf(p, "CPU%d.PMU %d\n", i, pmu_owners[i] ? pmu_owners[i]->pid: -1);
+		if (cpu_is_online(i))
+			p += sprintf(p, "CPU%d.PMU %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: 0);
 	}
 	return p - page;
 }
 
+/* for debug only */
 static int
 perfmon_read_entry(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
 	int len = perfmon_proc_info(page);
 
-        if (len <= off+count) *eof = 1;
+	if (len <= off+count) *eof = 1;
 
-        *start = page + off;
-        len   -= off;
+	*start = page + off;
+	len   -= off;
 
-        if (len>count) len = count;
-        if (len<0) len = 0;
+	if (len>count) len = count;
+	if (len<0) len = 0;
 
-        return len;
+	return len;
 }
 
-static struct proc_dir_entry *perfmon_dir;
+static struct irqaction perfmon_irqaction = {
+	handler:	perfmon_interrupt,
+	flags:		SA_INTERRUPT,
+	name:		"perfmon"
+};
 
 void __init
 perfmon_init (void)
 {
 	pal_perf_mon_info_u_t pm_info;
 	s64 status;
-	
-	irq_desc[PERFMON_IRQ].status |= IRQ_PER_CPU;
-	irq_desc[PERFMON_IRQ].handler = &irq_type_ia64_sapic;
-	setup_irq(PERFMON_IRQ, &perfmon_irqaction);
 
-	ia64_set_pmv(PERFMON_IRQ);
+	register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
+
+	ia64_set_pmv(IA64_PERFMON_VECTOR);
 	ia64_srlz_d();
 
-	printk("perfmon: Initialized vector to %u\n",PERFMON_IRQ);
+	pmu_conf.pfm_is_disabled = 1;
+
+	printk("perfmon: version %s\n", PFM_VERSION);
+	printk("perfmon: Interrupt vectored to %u\n", IA64_PERFMON_VECTOR);
 
 	if ((status=ia64_pal_perf_mon_info(pmu_conf.impl_regs, &pm_info)) != 0) {
-		printk(__FUNCTION__ " pal call failed (%ld)\n", status);
+		printk("perfmon: PAL call failed (%ld)\n", status);
 		return;
-	} 
-	pmu_conf.perf_ovfl_val = (1L << pm_info.pal_perf_mon_info_s.width) - 1; 
-
-	/* XXX need to use PAL instead */
+	}
+	pmu_conf.perf_ovfl_val = (1L << pm_info.pal_perf_mon_info_s.width) - 1;
 	pmu_conf.max_counters  = pm_info.pal_perf_mon_info_s.generic;
+	pmu_conf.num_pmds      = find_num_pm_regs(pmu_conf.impl_regs);
+	pmu_conf.num_pmcs      = find_num_pm_regs(&pmu_conf.impl_regs[4]);
 
 	printk("perfmon: Counters are %d bits\n", pm_info.pal_perf_mon_info_s.width);
 	printk("perfmon: Maximum counter value 0x%lx\n", pmu_conf.perf_ovfl_val);
+	printk("perfmon: %ld PMC/PMD pairs\n", pmu_conf.max_counters);
+	printk("perfmon: %ld PMCs, %ld PMDs\n", pmu_conf.num_pmcs, pmu_conf.num_pmds);
+	printk("perfmon: Sampling format v%d\n", PFM_SMPL_HDR_VERSION);
+
+	/* sanity check */
+	if (pmu_conf.num_pmds >= IA64_NUM_PMD_REGS || pmu_conf.num_pmcs >= IA64_NUM_PMC_REGS) {
+		printk(KERN_ERR "perfmon: ERROR not enough PMC/PMD storage in kernel, perfmon is DISABLED\n");
+		return; /* no need to continue anyway */
+	}
+	/* we are all set */
+	pmu_conf.pfm_is_disabled = 0;
+
+	/*
+	 * Insert the tasklet in the list.
+	 * It is still disabled at this point, so it won't run
+	printk(__FUNCTION__" tasklet is %p state=%d, count=%d\n", &perfmon_tasklet, perfmon_tasklet.state, perfmon_tasklet.count);
+	 */
 
 	/*
 	 * for now here for debug purposes
@@ -547,7 +1687,7 @@
 void
 perfmon_init_percpu (void)
 {
-	ia64_set_pmv(PERFMON_IRQ);
+	ia64_set_pmv(IA64_PERFMON_VECTOR);
 	ia64_srlz_d();
 }
 
@@ -555,14 +1695,19 @@
  * XXX: for system wide this function MUST never be called
  */
 void
-ia64_save_pm_regs (struct task_struct *ta)
+pfm_save_regs (struct task_struct *ta)
 {
-	struct thread_struct *t = &ta->thread;
+	struct task_struct *owner;
+	struct thread_struct *t;
 	u64 pmc0, psr;
-	int i,j;
+	int i;
 
+	if (ta == NULL) {
+		panic(__FUNCTION__" task is NULL\n");
+	}
+	t = &ta->thread;
 	/*
-	 * We must maek sure that we don't loose any potential overflow
+	 * We must make sure that we don't loose any potential overflow
 	 * interrupt while saving PMU context. In this code, external
 	 * interrupts are always enabled.
 	 */
@@ -575,94 +1720,102 @@
 	/*
 	 * stop monitoring:
 	 * This is the only way to stop monitoring without destroying overflow
-	 * information in PMC[0..3].
+	 * information in PMC[0].
 	 * This is the last instruction which can cause overflow when monitoring
 	 * in kernel.
-	 * By now, we could still have an overflow interrupt in flight.
+	 * By now, we could still have an overflow interrupt in-flight.
 	 */
-	__asm__ __volatile__ ("rsm psr.up;;"::: "memory");
-	
+	__asm__ __volatile__ ("rum psr.up;;"::: "memory");
+
+	/*
+	 * Mark the PMU as not owned
+	 * This will cause the interrupt handler to do nothing in case an overflow
+	 * interrupt was in-flight
+	 * This also guarantees that pmc0 will contain the final state
+	 * It virtually gives us full control over overflow processing from that point
+	 * on.
+	 * It must be an atomic operation.
+	 */
+	owner = PMU_OWNER();
+	SET_PMU_OWNER(NULL);
+
 	/*
 	 * read current overflow status:
 	 *
-	 * We may be reading stale information at this point, if we got interrupt
-	 * just before the read(pmc0) but that's all right. However, if we did
-	 * not get the interrupt before, this read reflects LAST state.
-	 *
+	 * we are guaranteed to read the final stable state
 	 */
-	pmc0 = ia64_get_pmc(0);
+	ia64_srlz_d();
+	pmc0 = ia64_get_pmc(0); /* slow */
 
 	/*
 	 * freeze PMU:
 	 *
 	 * This destroys the overflow information. This is required to make sure
 	 * next process does not start with monitoring on if not requested
-	 * (PSR.up may not be enough).
-	 *
-	 * We could still get an overflow interrupt by now. However the handler
-	 * will not do anything if is sees PMC[0].fr=1 but no overflow bits
-	 * are set. So PMU will stay in frozen state. This implies that pmc0
-	 * will still be holding the correct unprocessed information.
-	 *
 	 */
 	ia64_set_pmc(0, 1);
 	ia64_srlz_d();
 
 	/*
-	 * check for overflow bits set:
+	 * Check for overflow bits and proceed manually if needed
 	 *
-	 * If pmc0 reports PMU frozen, this means we have a pending overflow,
-	 * therefore we invoke the handler. Handler is reentrant with regards
-	 * to PMC[0] so it is safe to call it twice.
-	 *
-	 * IF pmc0 reports overflow, we need to reread current PMC[0] value
-	 * in case the handler was invoked right after the first pmc0 read.
-	 * it is was not invoked then pmc0==PMC[0], otherwise it's been invoked
-	 * and overflow information has been processed, so we don't need to call.
-	 *
-	 * Test breakdown:
-	 *	- pmc0 & ~0x1: test if overflow happened
-	 * 	- second part: check if current register reflects this as well.
-	 *
-	 * NOTE: testing for pmc0 & 0x1 is not enough has it would trigger call
-	 * when PM_VALID and PMU.fr which is common when setting up registers
-	 * just before actually starting monitors.
-	 *
-	 */
-	if ((pmc0 & ~0x1) && ((pmc0=ia64_get_pmc(0)) &~0x1) ) {
-		printk(__FUNCTION__" Warning: pmc[0]=0x%lx\n", pmc0);
-		update_counters(pmc0);
-		/* 
-		 * XXX: not sure that's enough. the next task may still get the
-		 * interrupt.
-		 */
+	 * It is safe to call the interrupt handler now because it does
+	 * not try to block the task right away. Instead it will set a
+	 * flag and let the task proceed. The blocking will only occur
+	 * next time the task exits from the kernel.
+	 */
+	if (pmc0 & ~0x1) {
+		if (owner != ta) printk(__FUNCTION__" owner=%p task=%p\n", (void *)owner, (void *)ta);
+		printk(__FUNCTION__" Warning: pmc[0]=0x%lx explicit call\n", pmc0);
+
+		pmc0 = update_counters(owner, pmc0, NULL);
+		/* we will save the updated version of pmc0 */
 	}
 
 	/*
 	 * restore PSR for context switch to save
 	 */
-	__asm__ __volatile__ ("mov psr.l=%0;;"::"r"(psr): "memory");
+	__asm__ __volatile__ ("mov psr.l=%0;; srlz.i;;"::"r"(psr): "memory");
+
 
 	/*
-	 * XXX: this will need to be extended beyong just counters
+	 * XXX needs further optimization.
+	 * Also must take holes into account
 	 */
-	for (i=0,j=4; i< IA64_NUM_PMD_COUNTERS; i++,j++) {
-		t->pmd[i] = ia64_get_pmd(j);
-		t->pmc[i] = ia64_get_pmc(j);
+	for (i=0; i< pmu_conf.num_pmds; i++) {
+		t->pmd[i] = ia64_get_pmd(i);
+	}
+
+	/* skip PMC[0], we handle it separately */
+	for (i=1; i< pmu_conf.num_pmcs; i++) {
+		t->pmc[i] = ia64_get_pmc(i);
 	}
+
 	/*
-	 * PMU is frozen, PMU context is saved: nobody owns the PMU on this CPU
-	 * At this point, we should not receive any pending interrupt from the 
-	 * 'switched out' task
+	 * Throughout this code we could have gotten an overflow interrupt. It is transformed
+	 * into a spurious interrupt as soon as we give up pmu ownership.
 	 */
-	pmu_owners[smp_processor_id()] = NULL;
 }
 
 void
-ia64_load_pm_regs (struct task_struct *ta)
+pfm_load_regs (struct task_struct *ta)
 {
 	struct thread_struct *t = &ta->thread;
-	int i,j;
+	pfm_context_t *ctx = ta->thread.pfm_context;
+	int i;
+
+	/*
+	 * XXX needs further optimization.
+	 * Also must take holes into account
+	 */
+	for (i=0; i< pmu_conf.num_pmds; i++) {
+		ia64_set_pmd(i, t->pmd[i]);
+	}
+
+	/* skip PMC[0] to avoid side effects */
+	for (i=1; i< pmu_conf.num_pmcs; i++) {
+		ia64_set_pmc(i, t->pmc[i]);
+	}
 
 	/*
 	 * we first restore ownership of the PMU to the 'soon to be current'
@@ -670,26 +1823,277 @@
 	 * of this function, we get an interrupt, we attribute it to the correct
 	 * task
 	 */
-	pmu_owners[smp_processor_id()] = ta;
+	SET_PMU_OWNER(ta);
+
+#if 0
+	/*
+	 * check if we had pending overflow before context switching out
+	 * If so, we invoke the handler manually, i.e. simulate interrupt.
+	 *
+	 * XXX: given that we do not use the tasklet anymore to stop, we can
+	 * move this back to the pfm_save_regs() routine.
+	 */
+	if (t->pmc[0] & ~0x1) {
+		/* freeze set in pfm_save_regs() */
+		DBprintk((" pmc[0]=0x%lx manual interrupt\n",t->pmc[0]));
+		update_counters(ta, t->pmc[0], NULL);
+	}
+#endif
 
 	/*
-	 * XXX: this will need to be extended beyong just counters 
+	 * unfreeze only when possible
 	 */
-	for (i=0,j=4; i< IA64_NUM_PMD_COUNTERS; i++,j++) {
-		ia64_set_pmd(j, t->pmd[i]);
-		ia64_set_pmc(j, t->pmc[i]);
+	if (ctx->ctx_fl_frozen == 0) {
+		ia64_set_pmc(0, 0);
+		ia64_srlz_d();
+	}
+}
+
+
+/*
+ * This function is called when a thread exits (from exit_thread()).
+ * This is a simplified pfm_save_regs() that simply flushes hthe current
+ * register state into the save area taking into account any pending
+ * overflow. This time no notification is sent because the taks is dying
+ * anyway. The inline processing of overflows avoids loosing some counts.
+ * The PMU is frozen on exit from this call and is to never be reenabled
+ * again for this task.
+ */
+void
+pfm_flush_regs (struct task_struct *ta)
+{
+	pfm_context_t *ctx;
+	u64 pmc0, psr, mask;
+	int i,j;
+
+	if (ta == NULL) {
+		panic(__FUNCTION__" task is NULL\n");
 	}
+	ctx = ta->thread.pfm_context;
+	if (ctx == NULL) {
+		panic(__FUNCTION__" no PFM ctx is NULL\n");
+	}
+	/*
+	 * We must make sure that we don't loose any potential overflow
+	 * interrupt while saving PMU context. In this code, external
+	 * interrupts are always enabled.
+	 */
+
+	/*
+	 * save current PSR: needed because we modify it
+	 */
+	__asm__ __volatile__ ("mov %0=psr;;": "=r"(psr) :: "memory");
+
+	/*
+	 * stop monitoring:
+	 * This is the only way to stop monitoring without destroying overflow
+	 * information in PMC[0].
+	 * This is the last instruction which can cause overflow when monitoring
+	 * in kernel.
+	 * By now, we could still have an overflow interrupt in-flight.
+	 */
+	__asm__ __volatile__ ("rsm psr.up;;"::: "memory");
+
+	/*
+	 * Mark the PMU as not owned
+	 * This will cause the interrupt handler to do nothing in case an overflow
+	 * interrupt was in-flight
+	 * This also guarantees that pmc0 will contain the final state
+	 * It virtually gives us full control on overflow processing from that point
+	 * on.
+	 * It must be an atomic operation.
+	 */
+	SET_PMU_OWNER(NULL);
+
+	/*
+	 * read current overflow status:
+	 *
+	 * we are guaranteed to read the final stable state
+	 */
+	ia64_srlz_d();
+	pmc0 = ia64_get_pmc(0); /* slow */
+
+	/*
+	 * freeze PMU:
+	 *
+	 * This destroys the overflow information. This is required to make sure
+	 * next process does not start with monitoring on if not requested
+	 */
+	ia64_set_pmc(0, 1);
+	ia64_srlz_d();
+
+	/*
+	 * restore PSR for context switch to save
+	 */
+	__asm__ __volatile__ ("mov psr.l=%0;;srlz.i;"::"r"(psr): "memory");
+
 	/*
-	 * unfreeze PMU
+	 * This loop flushes the PMD into the PFM context.
+	 * IT also processes overflow inline.
+	 *
+	 * IMPORTANT: No notification is sent at this point as the process is dying.
+	 * The implicit notification will come from a SIGCHILD or a return from a
+	 * waitpid().
+	 *
+	 * XXX: must take holes into account
 	 */
-	ia64_set_pmc(0, 0);
+	mask = pmc0 >> PMU_FIRST_COUNTER;
+	for (i=0,j=PMU_FIRST_COUNTER; i< pmu_conf.max_counters; i++,j++) {
+
+		/* collect latest results */
+		ctx->ctx_pmds[i].val += ia64_get_pmd(j) & pmu_conf.perf_ovfl_val;
+
+		/* take care of overflow inline */
+		if (mask & 0x1) {
+			ctx->ctx_pmds[i].val += 1 + pmu_conf.perf_ovfl_val;
+			DBprintk((" PMD[%d] overflowed pmd=0x%lx pmds.val=0x%lx\n",
+			j, ia64_get_pmd(j), ctx->ctx_pmds[i].val));
+		}
+	}
+}
+
+/*
+ * XXX: this routine is not very portable for PMCs
+ * XXX: make this routine able to work with non current context
+ */
+static void
+ia64_reset_pmu(void)
+{
+	int i;
+
+	/* PMU is frozen, no pending overflow bits */
+	ia64_set_pmc(0,1);
+
+	/* extra overflow bits + counter configs cleared */
+	for(i=1; i< PMU_FIRST_COUNTER + pmu_conf.max_counters ; i++) {
+		ia64_set_pmc(i,0);
+	}
+
+	/* opcode matcher set to all 1s */
+	ia64_set_pmc(8,~0);
+	ia64_set_pmc(9,~0);
+
+	/* I-EAR config cleared, plm=0 */
+	ia64_set_pmc(10,0);
+
+	/* D-EAR config cleared, PMC[11].pt must be 1 */
+	ia64_set_pmc(11,1 << 28);
+
+	/* BTB config. plm=0 */
+	ia64_set_pmc(12,0);
+
+	/* Instruction address range, PMC[13].ta must be 1 */
+	ia64_set_pmc(13,1);
+
+	/* clears all PMD registers */
+	for(i=0;i< pmu_conf.num_pmds; i++) {
+		if (PMD_IS_IMPL(i)) ia64_set_pmd(i,0);
+	}
 	ia64_srlz_d();
 }
 
+/*
+ * task is the newly created task
+ */
+int
+pfm_inherit(struct task_struct *task)
+{
+	pfm_context_t *ctx = current->thread.pfm_context;
+	pfm_context_t *nctx;
+	struct thread_struct *th = &task->thread;
+	int i, cnum;
+
+	/*
+	 * takes care of easiest case first
+	 */
+	if (CTX_INHERIT_MODE(ctx) == PFM_FL_INHERIT_NONE) {
+		DBprintk((" removing PFM context for %d\n", task->pid));
+		task->thread.pfm_context     = NULL;
+		task->thread.pfm_pend_notify = 0;
+		/* copy_thread() clears IA64_THREAD_PM_VALID */
+		return 0;
+	}
+	nctx = pfm_context_alloc();
+	if (nctx == NULL) return -ENOMEM;
+
+	/* copy content */
+	*nctx = *ctx;
+
+	if (ctx->ctx_fl_inherit == PFM_FL_INHERIT_ONCE) {
+		nctx->ctx_fl_inherit = PFM_FL_INHERIT_NONE;
+		DBprintk((" downgrading to INHERIT_NONE for %d\n", task->pid));
+	}
+
+	/* initialize counters in new context */
+	for(i=0, cnum= PMU_FIRST_COUNTER; i < pmu_conf.max_counters; cnum++, i++) {
+		nctx->ctx_pmds[i].val = nctx->ctx_pmds[i].ival & ~pmu_conf.perf_ovfl_val;
+		th->pmd[cnum]	      = nctx->ctx_pmds[i].ival & pmu_conf.perf_ovfl_val;
+
+	}
+	/* clear BTB index register */
+	th->pmd[16] = 0;
+
+	/* if sampling then increment number of users of buffer */
+	if (nctx->ctx_smpl_buf) {
+		atomic_inc(&nctx->ctx_smpl_buf->psb_refcnt);
+	}
+
+	nctx->ctx_fl_frozen = 0;
+	nctx->ctx_ovfl_regs = 0;
+	sema_init(&nctx->ctx_restart_sem, 0); /* reset this semaphore to locked */
+
+	/* clear pending notification */
+	th->pfm_pend_notify = 0;
+
+	/* link with new task */
+	th->pfm_context     = nctx;
+
+	DBprintk((" nctx=%p for process %d\n", (void *)nctx, task->pid));
+
+	/*
+	 * the copy_thread routine automatically clears
+	 * IA64_THREAD_PM_VALID, so we need to reenable it, if it was used by the caller
+	 */
+	if (current->thread.flags & IA64_THREAD_PM_VALID) {
+		DBprintk(("  setting PM_VALID for %d\n", task->pid));
+		th->flags |= IA64_THREAD_PM_VALID;
+	}
+
+	return 0;
+}
+
+/* called from exit_thread() */
+void
+pfm_context_exit(struct task_struct *task)
+{
+	pfm_context_t *ctx = task->thread.pfm_context;
+
+	if (!ctx) {
+		DBprintk((" invalid context for %d\n", task->pid));
+		return;
+	}
+
+	/* check is we have a sampling buffer attached */
+	if (ctx->ctx_smpl_buf) {
+		pfm_smpl_buffer_desc_t *psb = ctx->ctx_smpl_buf;
+
+		/* if only user left, then remove */
+		DBprintk((" pid %d: task %d sampling psb->refcnt=%d\n", current->pid, task->pid, psb->psb_refcnt.counter));
+
+		if (atomic_dec_and_test(&psb->psb_refcnt) ) {
+			rvfree(psb->psb_hdr, psb->psb_size);
+			vfree(psb);
+			DBprintk((" pid %d: cleaning task %d sampling buffer\n", current->pid, task->pid ));
+		}
+	}
+	DBprintk((" pid %d: task %d pfm_context is freed @%p\n", current->pid, task->pid, (void *)ctx));
+	pfm_context_free(ctx);
+}
+
 #else /* !CONFIG_PERFMON */
 
-asmlinkage unsigned long
-sys_perfmonctl (int cmd, int count, void *ptr)
+asmlinkage int
+sys_perfmonctl (int pid, int cmd, int flags, perfmon_req_t *req, int count, long arg6, long arg7, long arg8, long stack)
 {
 	return -ENOSYS;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/process.c linux/arch/ia64/kernel/process.c
--- v2.4.3/linux/arch/ia64/kernel/process.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/process.c	Thu Apr  5 12:51:47 2001
@@ -1,8 +1,8 @@
 /*
  * Architecture-specific setup.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #define __KERNEL_SYSCALLS__	/* see <asm/unistd.h> */
 #include <linux/config.h>
@@ -20,6 +20,7 @@
 
 #include <asm/delay.h>
 #include <asm/efi.h>
+#include <asm/perfmon.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/sal.h>
@@ -27,8 +28,6 @@
 #include <asm/unwind.h>
 #include <asm/user.h>
 
-#ifdef CONFIG_IA64_NEW_UNWIND
-
 static void
 do_show_stack (struct unw_frame_info *info, void *arg)
 {
@@ -46,12 +45,9 @@
 	} while (unw_unwind(info) >= 0);
 }
 
-#endif
-
 void
 show_stack (struct task_struct *task)
 {
-#ifdef CONFIG_IA64_NEW_UNWIND
 	if (!task)
 		unw_init_running(do_show_stack, 0);
 	else {
@@ -60,7 +56,6 @@
 		unw_init_from_blocked_task(&info, task);
 		do_show_stack(&info, 0);
 	}
-#endif
 }
 
 void
@@ -108,10 +103,8 @@
 			       ((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
 		}
 	}
-#ifdef CONFIG_IA64_NEW_UNWIND
 	if (!user_mode(regs))
 		show_stack(0);
-#endif
 }
 
 void __attribute__((noreturn))
@@ -147,7 +140,7 @@
 		ia64_save_debug_regs(&task->thread.dbr[0]);
 #ifdef CONFIG_PERFMON
 	if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
-		ia64_save_pm_regs(task);
+		pfm_save_regs(task);
 #endif
 	if (IS_IA32_PROCESS(ia64_task_regs(task)))
 		ia32_save_state(&task->thread);
@@ -160,7 +153,7 @@
 		ia64_load_debug_regs(&task->thread.dbr[0]);
 #ifdef CONFIG_PERFMON
 	if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
-		ia64_load_pm_regs(task);
+		pfm_load_regs(task);
 #endif
 	if (IS_IA32_PROCESS(ia64_task_regs(task)))
 		ia32_load_state(&task->thread);
@@ -210,6 +203,7 @@
 	struct switch_stack *child_stack, *stack;
 	extern char ia64_ret_from_clone;
 	struct pt_regs *child_ptregs;
+	int retval = 0;
 
 #ifdef CONFIG_SMP
 	/*
@@ -290,15 +284,17 @@
 	if (IS_IA32_PROCESS(ia64_task_regs(current)))
 		ia32_save_state(&p->thread);
 #endif
-	return 0;
+#ifdef CONFIG_PERFMON
+	if (current->thread.pfm_context)
+		retval = pfm_inherit(p);
+#endif
+	return retval;
 }
 
-#ifdef CONFIG_IA64_NEW_UNWIND
-
 void
 do_copy_regs (struct unw_frame_info *info, void *arg)
 {
-	unsigned long ar_bsp, ndirty, *krbs, addr, mask, sp, nat_bits = 0, ip;
+	unsigned long ar_bsp, addr, mask, sp, nat_bits = 0, ip, ar_rnat;
 	elf_greg_t *dst = arg;
 	struct pt_regs *pt;
 	char nat;
@@ -313,18 +309,18 @@
 	unw_get_sp(info, &sp);
 	pt = (struct pt_regs *) (sp + 16);
 
-	krbs = (unsigned long *) current + IA64_RBS_OFFSET/8;
-	ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
-	ar_bsp = (unsigned long) ia64_rse_skip_regs((long *) pt->ar_bspstore, ndirty);
+	ar_bsp = ia64_get_user_bsp(current, pt);
 
 	/*
-	 * Write portion of RSE backing store living on the kernel
-	 * stack to the VM of the process.
+	 * Write portion of RSE backing store living on the kernel stack to the VM of the
+	 * process.
 	 */
 	for (addr = pt->ar_bspstore; addr < ar_bsp; addr += 8)
-		if (ia64_peek(pt, current, addr, &val) == 0)
+		if (ia64_peek(current, ar_bsp, addr, &val) == 0)
 			access_process_vm(current, addr, &val, sizeof(val), 1);
 
+	ia64_peek(current, ar_bsp, (long) ia64_rse_rnat_addr((long *) addr - 1), &ar_rnat);
+
 	/*
 	 * coredump format:
 	 *	r0-r31
@@ -361,7 +357,7 @@
 	 */
 	dst[46] = ar_bsp;
 	dst[47] = pt->ar_bspstore;
-	unw_get_ar(info, UNW_AR_RNAT, &dst[48]);
+	dst[48] = ar_rnat;
 	unw_get_ar(info, UNW_AR_CCV, &dst[49]);
 	unw_get_ar(info, UNW_AR_UNAT, &dst[50]);
 	unw_get_ar(info, UNW_AR_FPSR, &dst[51]);
@@ -391,91 +387,16 @@
 		memcpy(dst + 32, current->thread.fph, 96*16);
 }
 
-#endif /* CONFIG_IA64_NEW_UNWIND */
-
 void
 ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
 {
-#ifdef CONFIG_IA64_NEW_UNWIND
 	unw_init_running(do_copy_regs, dst);
-#else
-	struct switch_stack *sw = ((struct switch_stack *) pt) - 1;
-	unsigned long ar_ec, cfm, ar_bsp, ndirty, *krbs, addr;
-
-	ar_ec = (sw->ar_pfs >> 52) & 0x3f;
-
-	cfm = pt->cr_ifs & ((1UL << 63) - 1);
-	if ((pt->cr_ifs & (1UL << 63)) == 0) {
-		/* if cr_ifs isn't valid, we got here through a syscall or a break */
-		cfm = sw->ar_pfs & ((1UL << 38) - 1);
-	}
-
-	krbs = (unsigned long *) current + IA64_RBS_OFFSET/8;
-	ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
-	ar_bsp = (unsigned long) ia64_rse_skip_regs((long *) pt->ar_bspstore, ndirty);
-
-	/*
-	 * Write portion of RSE backing store living on the kernel
-	 * stack to the VM of the process.
-	 */
-	for (addr = pt->ar_bspstore; addr < ar_bsp; addr += 8) {
-		long val;
-		if (ia64_peek(pt, current, addr, &val) == 0)
-			access_process_vm(current, addr, &val, sizeof(val), 1);
-	}
-
-	/*	r0-r31
-	 *	NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
-	 *	predicate registers (p0-p63)
-	 *	b0-b7
-	 *	ip cfm user-mask
-	 *	ar.rsc ar.bsp ar.bspstore ar.rnat
-	 *	ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
-	 */
-	memset(dst, 0, sizeof(dst));	/* don't leak any "random" bits */
-
-	/* r0 is zero */   dst[ 1] =  pt->r1; dst[ 2] =  pt->r2; dst[ 3] = pt->r3;
-	dst[ 4] =  sw->r4; dst[ 5] =  sw->r5; dst[ 6] =  sw->r6; dst[ 7] = sw->r7;
-	dst[ 8] =  pt->r8; dst[ 9] =  pt->r9; dst[10] = pt->r10; dst[11] = pt->r11;
-	dst[12] = pt->r12; dst[13] = pt->r13; dst[14] = pt->r14; dst[15] = pt->r15;
-	memcpy(dst + 16, &pt->r16, 16*8);	/* r16-r31 are contiguous */
-
-	dst[32] = ia64_get_nat_bits(pt, sw);
-	dst[33] = pt->pr;
-
-	/* branch regs: */
-	dst[34] = pt->b0; dst[35] = sw->b1; dst[36] = sw->b2; dst[37] = sw->b3;
-	dst[38] = sw->b4; dst[39] = sw->b5; dst[40] = pt->b6; dst[41] = pt->b7;
-
-	dst[42] = pt->cr_iip + ia64_psr(pt)->ri;
-	dst[43] = pt->cr_ifs;
-	dst[44] = pt->cr_ipsr & IA64_PSR_UM;
-
-	dst[45] = pt->ar_rsc; dst[46] = ar_bsp; dst[47] = pt->ar_bspstore;  dst[48] = pt->ar_rnat;
-	dst[49] = pt->ar_ccv; dst[50] = pt->ar_unat; dst[51] = sw->ar_fpsr; dst[52] = pt->ar_pfs;
-	dst[53] = sw->ar_lc; dst[54] = (sw->ar_pfs >> 52) & 0x3f;
-#endif /* !CONFIG_IA64_NEW_UNWIND */
 }
 
 int
 dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
 {
-#ifdef CONFIG_IA64_NEW_UNWIND
 	unw_init_running(do_dump_fpu, dst);
-#else
-	struct switch_stack *sw = ((struct switch_stack *) pt) - 1;
-
-	memset(dst, 0, sizeof (dst));	/* don't leak any "random" bits */
-
-	/* f0 is 0.0 */  /* f1 is 1.0 */  dst[2] = sw->f2; dst[3] = sw->f3;
-	dst[4] = sw->f4; dst[5] = sw->f5; dst[6] = pt->f6; dst[7] = pt->f7;
-	dst[8] = pt->f8; dst[9] = pt->f9;
-	memcpy(dst + 10, &sw->f10, 22*16);	/* f10-f31 are contiguous */
-
-	ia64_flush_fph(current);
-	if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0)
-		memcpy(dst + 32, current->thread.fph, 96*16);
-#endif
 	return 1;	/* f0-f31 are always valid so we always return 1 */
 }
 
@@ -523,6 +444,15 @@
 #endif
 }
 
+#ifdef CONFIG_PERFMON
+void
+release_thread (struct task_struct *task)
+{
+	if (task->thread.pfm_context)
+		pfm_context_exit(task);
+}
+#endif
+
 /*
  * Clean up state associated with current thread.  This is called when
  * the thread calls exit().
@@ -545,7 +475,7 @@
 		 * we garantee no race.  this call we also stop
 		 * monitoring
 		 */
-		ia64_save_pm_regs(current);
+		pfm_flush_regs(current);
 		/*
 		 * make sure that switch_to() will not save context again
 		 */
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/ptrace.c linux/arch/ia64/kernel/ptrace.c
--- v2.4.3/linux/arch/ia64/kernel/ptrace.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/ia64/kernel/ptrace.c	Thu Apr  5 12:51:47 2001
@@ -1,8 +1,8 @@
 /*
  * Kernel support for the ptrace() and syscall tracing interfaces.
  *
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Derived from the x86 and Alpha versions.  Most of the code in here
  * could actually be factored into a common set of routines.
@@ -22,6 +22,7 @@
 #include <asm/rse.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/unwind.h>
 
 /*
  * Bits in the PSR that we allow ptrace() to change:
@@ -36,8 +37,6 @@
 	(IA64_PSR_UM | IA64_PSR_DB | IA64_PSR_IS | IA64_PSR_ID | IA64_PSR_DD | IA64_PSR_RI)
 #define IPSR_READ_MASK	IPSR_WRITE_MASK
 
-#ifdef CONFIG_IA64_NEW_UNWIND
-
 #define PTRACE_DEBUG	1
 
 #if PTRACE_DEBUG
@@ -97,57 +96,6 @@
 #	undef PUT_BITS
 }
 
-#else /* !CONFIG_IA64_NEW_UNWIND */
-
-/*
- * Collect the NaT bits for r1-r31 from sw->caller_unat and
- * sw->ar_unat and return a NaT bitset where bit i is set iff the NaT
- * bit of register i is set.
- */
-long
-ia64_get_nat_bits (struct pt_regs *pt, struct switch_stack *sw)
-{
-#	define GET_BITS(str, first, last, unat)						\
-	({										\
-		unsigned long bit = ia64_unat_pos(&str->r##first);			\
-		unsigned long mask = ((1UL << (last - first + 1)) - 1) << first;	\
-		(ia64_rotl(unat, first) >> bit) & mask;					\
-	})
-	unsigned long val;
-
-	val  = GET_BITS(pt,  1,  3, sw->caller_unat);
-	val |= GET_BITS(pt, 12, 15, sw->caller_unat);
-	val |= GET_BITS(pt,  8, 11, sw->caller_unat);
-	val |= GET_BITS(pt, 16, 31, sw->caller_unat);
-	val |= GET_BITS(sw,  4,  7, sw->ar_unat);
-	return val;
-
-#	undef GET_BITS
-}
-
-/*
- * Store the NaT bitset NAT in pt->caller_unat and sw->ar_unat.
- */
-void
-ia64_put_nat_bits (struct pt_regs *pt, struct switch_stack *sw, unsigned long nat)
-{
-#	define PUT_BITS(str, first, last, nat)					\
-	({									\
-		unsigned long bit = ia64_unat_pos(&str->r##first);		\
-		unsigned long mask = ((1UL << (last - first + 1)) - 1) << bit;	\
-		(ia64_rotr(nat, first) << bit) & mask;				\
-	})
-	sw->caller_unat  = PUT_BITS(pt,  1,  3, nat);
-	sw->caller_unat |= PUT_BITS(pt, 12, 15, nat);
-	sw->caller_unat |= PUT_BITS(pt,  8, 11, nat);
-	sw->caller_unat |= PUT_BITS(pt, 16, 31, nat);
-	sw->ar_unat      = PUT_BITS(sw,  4,  7, nat);
-
-#	undef PUT_BITS
-}
-
-#endif /* !CONFIG_IA64_NEW_UNWIND */
-
 #define IA64_MLX_TEMPLATE	0x2
 #define IA64_MOVL_OPCODE	6
 
@@ -215,7 +163,7 @@
  * | slot01 | > child_regs->ar_rnat
  * +--------+ |
  * | slot02 | /				kernel rbs
- * +--------+ 				+--------+
+ * +--------+				+--------+
  *	    <- child_regs->ar_bspstore	| slot61 | <-- krbs
  * +- - - - +				+--------+
  *					| slot62 |
@@ -275,7 +223,7 @@
 		/* some bits need to be merged in from pt->ar_rnat */
 		kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1);
 		urnat = (pt->ar_rnat & ~kmask);
-	} 
+	}
 	if (rnat0_kaddr >= kbsp) {
 		rnat0 = sw->ar_rnat;
 	} else if (rnat0_kaddr > krbs) {
@@ -319,7 +267,7 @@
 		/* some bits need to be place in pt->ar_rnat: */
 		kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1);
 		pt->ar_rnat = (pt->ar_rnat & kmask) | (rnat & ~kmask);
-	} 
+	}
 	/*
 	 * Note: Section 11.1 of the EAS guarantees that bit 63 of an
 	 * rnat slot is ignored. so we don't have to clear it here.
@@ -342,9 +290,9 @@
 }
 
 long
-ia64_peek (struct pt_regs *regs, struct task_struct *child, unsigned long addr, long *val)
+ia64_peek (struct task_struct *child, unsigned long user_bsp, unsigned long addr, long *val)
 {
-	unsigned long *bspstore, *krbs, krbs_num_regs, regnum, *rbs_end, *laddr;
+	unsigned long *bspstore, *krbs, regnum, *laddr, *ubsp = (long *) user_bsp;
 	struct switch_stack *child_stack;
 	struct pt_regs *child_regs;
 	size_t copied;
@@ -352,35 +300,22 @@
 
 	laddr = (unsigned long *) addr;
 	child_regs = ia64_task_regs(child);
-#ifdef CONFIG_IA64_NEW_UNWIND
 	child_stack = (struct switch_stack *) (child->thread.ksp + 16);
-#else
-	child_stack = (struct switch_stack *) child_regs - 1;
-#endif
 	bspstore = (unsigned long *) child_regs->ar_bspstore;
 	krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
-	krbs_num_regs = ia64_rse_num_regs(krbs, (unsigned long *) child_stack->ar_bspstore);
-	rbs_end = ia64_rse_skip_regs(bspstore, krbs_num_regs);
-	if (laddr >= bspstore && laddr <= ia64_rse_rnat_addr(rbs_end)) {
+	if (laddr >= bspstore && laddr <= ia64_rse_rnat_addr(ubsp)) {
 		/*
-		 * Attempt to read the RBS in an area that's actually
-		 * on the kernel RBS => read the corresponding bits in
-		 * the kernel RBS.
+		 * Attempt to read the RBS in an area that's actually on the kernel RBS =>
+		 * read the corresponding bits in the kernel RBS.
 		 */
 		if (ia64_rse_is_rnat_slot(laddr))
 			ret = get_rnat(child_regs, child_stack, krbs, laddr);
 		else {
-			regnum = ia64_rse_num_regs(bspstore, laddr);
-			laddr = ia64_rse_skip_regs(krbs, regnum);
-			if (regnum >= krbs_num_regs) {
+			if (laddr >= ubsp)
 				ret = 0;
-			} else {
-				if  ((unsigned long) laddr >= (unsigned long) high_memory) {
-					printk("yikes: trying to access long at %p\n",
-					       (void *) laddr);
-					return -EIO;
-				}
-				ret = *laddr;
+			else {
+				regnum = ia64_rse_num_regs(bspstore, laddr);
+				ret = *ia64_rse_skip_regs(krbs, regnum);
 			}
 		}
 	} else {
@@ -393,36 +328,28 @@
 }
 
 long
-ia64_poke (struct pt_regs *regs, struct task_struct *child, unsigned long addr, long val)
+ia64_poke (struct task_struct *child, unsigned long user_bsp, unsigned long addr, long val)
 {
-	unsigned long *bspstore, *krbs, krbs_num_regs, regnum, *rbs_end, *laddr;
+	unsigned long *bspstore, *krbs, regnum, *laddr, *ubsp = (long *) user_bsp;
 	struct switch_stack *child_stack;
 	struct pt_regs *child_regs;
 
 	laddr = (unsigned long *) addr;
 	child_regs = ia64_task_regs(child);
-#ifdef CONFIG_IA64_NEW_UNWIND
 	child_stack = (struct switch_stack *) (child->thread.ksp + 16);
-#else
-	child_stack = (struct switch_stack *) child_regs - 1;
-#endif
 	bspstore = (unsigned long *) child_regs->ar_bspstore;
 	krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
-	krbs_num_regs = ia64_rse_num_regs(krbs, (unsigned long *) child_stack->ar_bspstore);
-	rbs_end = ia64_rse_skip_regs(bspstore, krbs_num_regs);
-	if (laddr >= bspstore && laddr <= ia64_rse_rnat_addr(rbs_end)) {
+	if (laddr >= bspstore && laddr <= ia64_rse_rnat_addr(ubsp)) {
 		/*
-		 * Attempt to write the RBS in an area that's actually
-		 * on the kernel RBS => write the corresponding bits
-		 * in the kernel RBS.
+		 * Attempt to write the RBS in an area that's actually on the kernel RBS
+		 * => write the corresponding bits in the kernel RBS.
 		 */
 		if (ia64_rse_is_rnat_slot(laddr))
 			put_rnat(child_regs, child_stack, krbs, laddr, val);
 		else {
-			regnum = ia64_rse_num_regs(bspstore, laddr);
-			laddr = ia64_rse_skip_regs(krbs, regnum);
-			if (regnum < krbs_num_regs) {
-				*laddr = val;
+			if (laddr < ubsp) {
+				regnum = ia64_rse_num_regs(bspstore, laddr);
+				*ia64_rse_skip_regs(krbs, regnum) = val;
 			}
 		}
 	} else if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val)) {
@@ -432,83 +359,76 @@
 }
 
 /*
- * Synchronize (i.e, write) the RSE backing store living in kernel
- * space to the VM of the indicated child process.
- *
- * If new_bsp is non-zero, the bsp will (effectively) be updated to
- * the new value upon resumption of the child process.  This is
- * accomplished by setting the loadrs value to zero and the bspstore
- * value to the new bsp value.
- *
- * When new_bsp and force_loadrs_to_zero are both 0, the register
- * backing store in kernel space is written to user space and the
- * loadrs and bspstore values are left alone.
- *
- * When new_bsp is zero and force_loadrs_to_zero is 1 (non-zero),
- * loadrs is set to 0, and the bspstore value is set to the old bsp
- * value.  This will cause the stacked registers (r32 and up) to be
- * obtained entirely from the child's memory space rather than
- * from the kernel.  (This makes it easier to write code for
- * modifying the stacked registers in multi-threaded programs.)
- *
- * Note:  I had originally written this function without the
- * force_loadrs_to_zero parameter; it was written so that loadrs would
- * always be set to zero.  But I had problems with certain system
- * calls apparently causing a portion of the RBS to be zeroed.  (I
- * still don't understand why this was happening.) Anyway, it'd
- * definitely less intrusive to leave loadrs and bspstore alone if
- * possible.
+ * Calculate the user-level address that would have been in ar.bsp had the user executed a
+ * "cover" instruction right before entering the kernel.
  */
-static long
-sync_kernel_register_backing_store (struct task_struct *child,
-                                    long new_bsp,
-                                    int force_loadrs_to_zero)
+unsigned long
+ia64_get_user_bsp (struct task_struct *child, struct pt_regs *pt)
 {
-	unsigned long *krbs, bspstore, *kbspstore, bsp, rbs_end, addr, val;
-	long ndirty, ret = 0;
-	struct pt_regs *child_regs = ia64_task_regs(child);
-
-#ifdef CONFIG_IA64_NEW_UNWIND
+	unsigned long *krbs, *bspstore, cfm;
 	struct unw_frame_info info;
-	unsigned long cfm, sof;
-
-	unw_init_from_blocked_task(&info, child);
-	if (unw_unwind_to_user(&info) < 0)
-		return -1;
-
-	unw_get_bsp(&info, (unsigned long *) &kbspstore);
+	long ndirty;
 
 	krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
-	ndirty = ia64_rse_num_regs(krbs, krbs + (child_regs->loadrs >> 19));
-	bspstore = child_regs->ar_bspstore;
-	bsp = (long) ia64_rse_skip_regs((long *)bspstore, ndirty);
-
-	cfm = child_regs->cr_ifs;
-	if (!(cfm & (1UL << 63)))
-		unw_get_cfm(&info, &cfm);
-	sof = (cfm & 0x7f);
-	rbs_end = (long) ia64_rse_skip_regs((long *)bspstore, sof);
-#else
-	struct switch_stack *child_stack;
-	unsigned long krbs_num_regs;
+	bspstore = (unsigned long *) pt->ar_bspstore;
+	ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
 
-	child_stack = (struct switch_stack *) child_regs - 1;
-	kbspstore = (unsigned long *) child_stack->ar_bspstore;
-	krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
-	ndirty = ia64_rse_num_regs(krbs, krbs + (child_regs->loadrs >> 19));
-	bspstore = child_regs->ar_bspstore;
-	bsp = (long) ia64_rse_skip_regs((long *)bspstore, ndirty);
-	krbs_num_regs = ia64_rse_num_regs(krbs, kbspstore);
-	rbs_end = (long) ia64_rse_skip_regs((long *)bspstore, krbs_num_regs);
-#endif
+	if ((long) pt->cr_ifs >= 0) {
+		/*
+		 * If bit 63 of cr.ifs is cleared, the kernel was entered via a system
+		 * call and we need to recover the CFM that existed on entry to the
+		 * kernel by unwinding the kernel stack.
+		 */
+		unw_init_from_blocked_task(&info, child);
+		if (unw_unwind_to_user(&info) == 0) {
+			unw_get_cfm(&info, &cfm);
+			ndirty += (cfm & 0x7f);
+		}
+	}
+	return (unsigned long) ia64_rse_skip_regs(bspstore, ndirty);
+}
 
-	/* Return early if nothing to do */
-	if (bsp == new_bsp)
+/*
+ * Synchronize (i.e, write) the RSE backing store living in kernel space to the VM of the
+ * indicated child process.
+ *
+ * If new_bsp is non-zero, the bsp will (effectively) be updated to the new value upon
+ * resumption of the child process.  This is accomplished by setting the loadrs value to
+ * zero and the bspstore value to the new bsp value.
+ *
+ * When new_bsp and flush_user_rbs are both 0, the register backing store in kernel space
+ * is written to user space and the loadrs and bspstore values are left alone.
+ *
+ * When new_bsp is zero and flush_user_rbs is 1 (non-zero), loadrs is set to 0, and the
+ * bspstore value is set to the old bsp value.  This will cause the stacked registers (r32
+ * and up) to be obtained entirely from the child's memory space rather than from the
+ * kernel.  (This makes it easier to write code for modifying the stacked registers in
+ * multi-threaded programs.)
+ *
+ * Note: I had originally written this function without the flush_user_rbs parameter; it
+ * was written so that loadrs would always be set to zero.  But I had problems with
+ * certain system calls apparently causing a portion of the RBS to be zeroed.  (I still
+ * don't understand why this was happening.) Anyway, it'd definitely less intrusive to
+ * leave loadrs and bspstore alone if possible.
+ */
+static long
+sync_kernel_register_backing_store (struct task_struct *child, long user_bsp, long new_bsp,
+				    int flush_user_rbs)
+{
+	struct pt_regs *child_regs = ia64_task_regs(child);
+	unsigned long addr, val;
+	long ret;
+
+	/*
+	 * Return early if nothing to do.  Note that new_bsp will be zero if the caller
+	 * wants to force synchronization without changing bsp.
+	 */
+	if (user_bsp == new_bsp)
 		return 0;
 
 	/* Write portion of backing store living on kernel stack to the child's VM. */
-	for (addr = bspstore; addr < rbs_end; addr += 8) {
-		ret = ia64_peek(child_regs, child, addr, &val);
+	for (addr = child_regs->ar_bspstore; addr < user_bsp; addr += 8) {
+		ret = ia64_peek(child, user_bsp, addr, &val);
 		if (ret != 0)
 			return ret;
 		if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val))
@@ -516,27 +436,26 @@
 	}
 
 	if (new_bsp != 0) {
-		force_loadrs_to_zero = 1;
-		bsp = new_bsp;
+		flush_user_rbs = 1;
+		user_bsp = new_bsp;
 	}
 
-	if (force_loadrs_to_zero) {
+	if (flush_user_rbs) {
 		child_regs->loadrs = 0;
-		child_regs->ar_bspstore = bsp;
+		child_regs->ar_bspstore = user_bsp;
 	}
-
-	return ret;
+	return 0;
 }
 
 static void
-sync_thread_rbs (struct task_struct *child, struct mm_struct *mm, int make_writable)
+sync_thread_rbs (struct task_struct *child, long bsp, struct mm_struct *mm, int make_writable)
 {
 	struct task_struct *p;
 	read_lock(&tasklist_lock);
 	{
 		for_each_task(p) {
 			if (p->mm == mm && p->state != TASK_RUNNING)
-				sync_kernel_register_backing_store(p, 0, make_writable);
+				sync_kernel_register_backing_store(p, bsp, 0, make_writable);
 		}
 	}
 	read_unlock(&tasklist_lock);
@@ -588,10 +507,6 @@
 	psr->dfh = 1;
 }
 
-#ifdef CONFIG_IA64_NEW_UNWIND
-
-#include <asm/unwind.h>
-
 static int
 access_fr (struct unw_frame_info *info, int regnum, int hi, unsigned long *data, int write_access)
 {
@@ -613,7 +528,7 @@
 static int
 access_uarea (struct task_struct *child, unsigned long addr, unsigned long *data, int write_access)
 {
-	unsigned long *ptr, *rbs, *bspstore, ndirty, regnum;
+	unsigned long *ptr, regnum, bsp, rnat_addr;
 	struct switch_stack *sw;
 	struct unw_frame_info info;
 	struct pt_regs *pt;
@@ -710,36 +625,16 @@
 		/* scratch state */
 		switch (addr) {
 		      case PT_AR_BSP:
+			bsp = ia64_get_user_bsp(child, pt);
 			if (write_access)
-				/* FIXME? Account for lack of ``cover'' in the syscall case */
-				return sync_kernel_register_backing_store(child, *data, 1);
+				return sync_kernel_register_backing_store(child, bsp, *data, 1);
 			else {
-				rbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
-				bspstore = (unsigned long *) pt->ar_bspstore;
-				ndirty = ia64_rse_num_regs(rbs, rbs + (pt->loadrs >> 19));
-
-				/*
-				 * If we're in a system call, no ``cover'' was done.  So to
-				 * make things uniform, we'll add the appropriate displacement
-				 * onto bsp if we're in a system call.
-				 */
-				if (!(pt->cr_ifs & (1UL << 63))) {
-					struct unw_frame_info info;
-					unsigned long cfm;
-
-					unw_init_from_blocked_task(&info, child);
-					if (unw_unwind_to_user(&info) < 0)
-						return -1;
-
-					unw_get_cfm(&info, &cfm);
-					ndirty += cfm & 0x7f;
-				}
-				*data = (unsigned long) ia64_rse_skip_regs(bspstore, ndirty);
+				*data = bsp;
 				return 0;
 			}
 
 		      case PT_CFM:
-			if (pt->cr_ifs & (1UL << 63)) {
+			if ((long) pt->cr_ifs < 0) {
 				if (write_access)
 					pt->cr_ifs = ((pt->cr_ifs & ~0x3fffffffffUL)
 						      | (*data & 0x3fffffffffUL));
@@ -770,7 +665,15 @@
 				*data = (pt->cr_ipsr & IPSR_READ_MASK);
 			return 0;
 
-		      		   case PT_R1:  case PT_R2:  case PT_R3:
+		      case PT_AR_RNAT:
+			bsp = ia64_get_user_bsp(child, pt);
+			rnat_addr = (long) ia64_rse_rnat_addr((long *) bsp - 1);
+			if (write_access)
+				return ia64_poke(child, bsp, rnat_addr, *data);
+			else
+				return ia64_peek(child, bsp, rnat_addr, data);
+
+				   case PT_R1:  case PT_R2:  case PT_R3:
 		      case PT_R8:  case PT_R9:  case PT_R10: case PT_R11:
 		      case PT_R12: case PT_R13: case PT_R14: case PT_R15:
 		      case PT_R16: case PT_R17: case PT_R18: case PT_R19:
@@ -781,7 +684,7 @@
 		      case PT_F6:  case PT_F6+8: case PT_F7: case PT_F7+8:
 		      case PT_F8:  case PT_F8+8: case PT_F9: case PT_F9+8:
 		      case PT_AR_BSPSTORE:
-		      case PT_AR_RSC: case PT_AR_UNAT: case PT_AR_PFS: case PT_AR_RNAT:
+		      case PT_AR_RSC: case PT_AR_UNAT: case PT_AR_PFS:
 		      case PT_AR_CCV: case PT_AR_FPSR: case PT_CR_IIP: case PT_PR:
 			/* scratch register */
 			ptr = (unsigned long *) ((long) pt + addr - PT_CR_IPSR);
@@ -799,7 +702,7 @@
 		if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
 			child->thread.flags |= IA64_THREAD_DBG_VALID;
 			memset(child->thread.dbr, 0, sizeof(child->thread.dbr));
-			memset(child->thread.ibr, 0, sizeof( child->thread.ibr));
+			memset(child->thread.ibr, 0, sizeof(child->thread.ibr));
 		}
 		if (addr >= PT_IBR) {
 			regnum = (addr - PT_IBR) >> 3;
@@ -830,173 +733,13 @@
 	return 0;
 }
 
-#else /* !CONFIG_IA64_NEW_UNWIND */
-
-static int
-access_uarea (struct task_struct *child, unsigned long addr, unsigned long *data, int write_access)
-{
-	unsigned long *ptr = NULL, *rbs, *bspstore, ndirty, regnum;
-	struct switch_stack *sw;
-	struct pt_regs *pt;
-
-	if ((addr & 0x7) != 0)
-		return -1;
-
-	if (addr < PT_F127+16) {
-		/* accessing fph */
-		if (write_access)
-			ia64_sync_fph(child);
-		else
-			ia64_flush_fph(child);
-		ptr = (unsigned long *) ((unsigned long) &child->thread.fph + addr);
-	} else if (addr < PT_F9+16) {
-		/* accessing switch_stack or pt_regs: */
-		pt = ia64_task_regs(child);
-		sw = (struct switch_stack *) pt - 1;
-
-		switch (addr) {
-		      case PT_NAT_BITS:
-			if (write_access)
-				ia64_put_nat_bits(pt, sw, *data);
-			else
-				*data = ia64_get_nat_bits(pt, sw);
-			return 0;
-
-		      case PT_AR_BSP:
-			if (write_access)
-				/* FIXME? Account for lack of ``cover'' in the syscall case */
-				return sync_kernel_register_backing_store(child, *data, 1);
-			else {
-				rbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
-				bspstore = (unsigned long *) pt->ar_bspstore;
-				ndirty = ia64_rse_num_regs(rbs, rbs + (pt->loadrs >> 19));
-
-				/*
-				 * If we're in a system call, no ``cover'' was done.  So to
-				 * make things uniform, we'll add the appropriate displacement
-				 * onto bsp if we're in a system call.
-				 */
-				if (!(pt->cr_ifs & (1UL << 63)))
-					ndirty += sw->ar_pfs & 0x7f;
-				*data = (unsigned long) ia64_rse_skip_regs(bspstore, ndirty);
-				return 0;
-			}
-
-		      case PT_CFM:
-			if (write_access) {
-				if (pt->cr_ifs & (1UL << 63))
-					pt->cr_ifs = ((pt->cr_ifs & ~0x3fffffffffUL)
-						      | (*data & 0x3fffffffffUL));
-				else
-					sw->ar_pfs = ((sw->ar_pfs & ~0x3fffffffffUL)
-						      | (*data & 0x3fffffffffUL));
-				return 0;
-			} else {
-				if ((pt->cr_ifs & (1UL << 63)) == 0)
-					*data = sw->ar_pfs;
-				else
-					/* return only the CFM */
-					*data = pt->cr_ifs & 0x3fffffffffUL;
-				return 0;
-			}
-
-		      case PT_CR_IPSR:
-			if (write_access)
-				pt->cr_ipsr = ((*data & IPSR_WRITE_MASK)
-					       | (pt->cr_ipsr & ~IPSR_WRITE_MASK));
-			else
-				*data = (pt->cr_ipsr & IPSR_READ_MASK);
-			return 0;
-
-		      case PT_AR_EC:
-			if (write_access)
-				sw->ar_pfs = (((*data & 0x3f) << 52)
-					      | (sw->ar_pfs & ~(0x3fUL << 52)));
-			else
-				*data = (sw->ar_pfs >> 52) & 0x3f;
-			break;
-
-		      case PT_R1: case PT_R2: case PT_R3:
-		      case PT_R4: case PT_R5: case PT_R6: case PT_R7:
-		      case PT_R8: case PT_R9: case PT_R10: case PT_R11:
-		      case PT_R12: case PT_R13: case PT_R14: case PT_R15:
-		      case PT_R16: case PT_R17: case PT_R18: case PT_R19:
-		      case PT_R20: case PT_R21: case PT_R22: case PT_R23:
-		      case PT_R24: case PT_R25: case PT_R26: case PT_R27:
-		      case PT_R28: case PT_R29: case PT_R30: case PT_R31:
-		      case PT_B0: case PT_B1: case PT_B2: case PT_B3:
-		      case PT_B4: case PT_B5: case PT_B6: case PT_B7:
-		      case PT_F2: case PT_F2+8: case PT_F3: case PT_F3+8:
-		      case PT_F4: case PT_F4+8: case PT_F5: case PT_F5+8:
-		      case PT_F6: case PT_F6+8: case PT_F7: case PT_F7+8:
-  		      case PT_F8: case PT_F8+8: case PT_F9: case PT_F9+8:
-		      case PT_F10: case PT_F10+8: case PT_F11: case PT_F11+8:
-		      case PT_F12: case PT_F12+8: case PT_F13: case PT_F13+8:
-		      case PT_F14: case PT_F14+8: case PT_F15: case PT_F15+8:
-		      case PT_F16: case PT_F16+8: case PT_F17: case PT_F17+8:
-		      case PT_F18: case PT_F18+8: case PT_F19: case PT_F19+8:
-  		      case PT_F20: case PT_F20+8: case PT_F21: case PT_F21+8:
-		      case PT_F22: case PT_F22+8: case PT_F23: case PT_F23+8: 
-		      case PT_F24: case PT_F24+8: case PT_F25: case PT_F25+8:
-		      case PT_F26: case PT_F26+8: case PT_F27: case PT_F27+8:
- 		      case PT_F28: case PT_F28+8: case PT_F29: case PT_F29+8:
-		      case PT_F30: case PT_F30+8: case PT_F31: case PT_F31+8:
-		      case PT_AR_BSPSTORE:
-		      case PT_AR_RSC: case PT_AR_UNAT: case PT_AR_PFS: case PT_AR_RNAT:
-		      case PT_AR_CCV: case PT_AR_FPSR: case PT_CR_IIP: case PT_PR:
-		      case PT_AR_LC:
-			ptr = (unsigned long *) ((long) sw + addr - PT_NAT_BITS);
-			break;
-
-		      default:
-			/* disallow accessing anything else... */
-			return -1;
-		}
-	} else {
-
-		/* access debug registers */
-
-		if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
-			child->thread.flags |= IA64_THREAD_DBG_VALID;
-			memset(child->thread.dbr, 0, sizeof child->thread.dbr);
-			memset(child->thread.ibr, 0, sizeof child->thread.ibr);
-		}
-		if (addr >= PT_IBR) {
-			regnum = (addr - PT_IBR) >> 3;
-			ptr = &child->thread.ibr[0];
-		} else {
-			regnum = (addr - PT_DBR) >> 3;
-			ptr = &child->thread.dbr[0];
-		}
-
-		if (regnum >= 8)
-			return -1;
-
-		ptr += regnum;
-
-		if (write_access)
-			/* don't let the user set kernel-level breakpoints... */
-			*ptr = *data & ~(7UL << 56);
-		else
-			*data = *ptr;
-		return 0;
-	}
-	if (write_access)
-		*ptr = *data;
-	else
-		*data = *ptr;
-	return 0;
-}
-
-#endif /* !CONFIG_IA64_NEW_UNWIND */
-
 asmlinkage long
 sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
 	    long arg4, long arg5, long arg6, long arg7, long stack)
 {
-	struct pt_regs *regs = (struct pt_regs *) &stack;
+	struct pt_regs *pt, *regs = (struct pt_regs *) &stack;
 	struct task_struct *child;
-	unsigned long flags;
+	unsigned long flags, bsp;
 	long ret;
 
 	lock_kernel();
@@ -1031,10 +774,10 @@
 		    (current->uid != child->euid) ||
 		    (current->uid != child->suid) ||
 		    (current->uid != child->uid) ||
-	 	    (current->gid != child->egid) ||
-	 	    (current->gid != child->sgid) ||
-	 	    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
-	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+		    (current->gid != child->egid) ||
+		    (current->gid != child->sgid) ||
+		    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+		    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
 			goto out_tsk;
 		/* the same process cannot be attached many times */
 		if (child->ptrace & PT_PTRACED)
@@ -1065,10 +808,13 @@
 	if (child->p_pptr != current)
 		goto out_tsk;
 
+	pt = ia64_task_regs(child);
+
 	switch (request) {
 	      case PTRACE_PEEKTEXT:
 	      case PTRACE_PEEKDATA:		/* read word at location addr */
-	        if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED)) {
+		bsp = ia64_get_user_bsp(child, pt);
+		if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED)) {
 			struct mm_struct *mm;
 			long do_sync;
 
@@ -1079,9 +825,9 @@
 			}
 			task_unlock(child);
 			if (do_sync)
-				sync_thread_rbs(child, mm, 0);
+				sync_thread_rbs(child, bsp, mm, 0);
 		}
-		ret = ia64_peek(regs, child, addr, &data);
+		ret = ia64_peek(child, bsp, addr, &data);
 		if (ret == 0) {
 			ret = data;
 			regs->r8 = 0;	/* ensure "ret" is not mistaken as an error code */
@@ -1090,7 +836,8 @@
 
 	      case PTRACE_POKETEXT:
 	      case PTRACE_POKEDATA:		/* write the word at location addr */
-	        if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED)) {
+		bsp = ia64_get_user_bsp(child, pt);
+		if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED)) {
 			struct mm_struct *mm;
 			long do_sync;
 
@@ -1101,9 +848,9 @@
 			}
 			task_unlock(child);
 			if (do_sync)
-				sync_thread_rbs(child, mm, 1);
+				sync_thread_rbs(child, bsp, mm, 1);
 		}
-		ret = ia64_poke(regs, child, addr, data);
+		ret = ia64_poke(child, bsp, addr, data);
 		goto out_tsk;
 
 	      case PTRACE_PEEKUSR:		/* read the word at addr in the USER area */
@@ -1125,21 +872,19 @@
 
 	      case PTRACE_GETSIGINFO:
 		ret = -EIO;
-		if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t))
-		    || child->thread.siginfo == 0)
+		if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t)) || !child->thread.siginfo)
 			goto out_tsk;
-		copy_to_user((siginfo_t *) data, child->thread.siginfo, sizeof (siginfo_t));
-		ret = 0;
+		ret = copy_siginfo_to_user((siginfo_t *) data, child->thread.siginfo);
 		goto out_tsk;
-		break;
+
 	      case PTRACE_SETSIGINFO:
 		ret = -EIO;
 		if (!access_ok(VERIFY_READ, data, sizeof (siginfo_t))
 		    || child->thread.siginfo == 0)
 			goto out_tsk;
-		copy_from_user(child->thread.siginfo, (siginfo_t *) data, sizeof (siginfo_t));
-		ret = 0;
+		ret = copy_siginfo_from_user(child->thread.siginfo, (siginfo_t *) data);
 		goto out_tsk;
+
 	      case PTRACE_SYSCALL:	/* continue and stop at next (return from) syscall */
 	      case PTRACE_CONT:		/* restart after signal. */
 		ret = -EIO;
@@ -1152,8 +897,8 @@
 		child->exit_code = data;
 
 		/* make sure the single step/take-branch tra bits are not set: */
-		ia64_psr(ia64_task_regs(child))->ss = 0;
-		ia64_psr(ia64_task_regs(child))->tb = 0;
+		ia64_psr(pt)->ss = 0;
+		ia64_psr(pt)->tb = 0;
 
 		/* Turn off flag indicating that the KRBS is sync'd with child's VM: */
 		child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED;
@@ -1173,8 +918,8 @@
 		child->exit_code = SIGKILL;
 
 		/* make sure the single step/take-branch tra bits are not set: */
-		ia64_psr(ia64_task_regs(child))->ss = 0;
-		ia64_psr(ia64_task_regs(child))->tb = 0;
+		ia64_psr(pt)->ss = 0;
+		ia64_psr(pt)->tb = 0;
 
 		/* Turn off flag indicating that the KRBS is sync'd with child's VM: */
 		child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED;
@@ -1191,9 +936,9 @@
 
 		child->ptrace &= ~PT_TRACESYS;
 		if (request == PTRACE_SINGLESTEP) {
-			ia64_psr(ia64_task_regs(child))->ss = 1;
+			ia64_psr(pt)->ss = 1;
 		} else {
-			ia64_psr(ia64_task_regs(child))->tb = 1;
+			ia64_psr(pt)->tb = 1;
 		}
 		child->exit_code = data;
 
@@ -1219,8 +964,8 @@
 		write_unlock_irqrestore(&tasklist_lock, flags);
 
 		/* make sure the single step/take-branch tra bits are not set: */
-		ia64_psr(ia64_task_regs(child))->ss = 0;
-		ia64_psr(ia64_task_regs(child))->tb = 0;
+		ia64_psr(pt)->ss = 0;
+		ia64_psr(pt)->tb = 0;
 
 		/* Turn off flag indicating that the KRBS is sync'd with child's VM: */
 		child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/semaphore.c linux/arch/ia64/kernel/semaphore.c
--- v2.4.3/linux/arch/ia64/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/ia64/kernel/semaphore.c	Tue Apr 17 17:19:24 2001
@@ -155,180 +155,3 @@
 	spin_unlock_irqrestore(&semaphore_lock, flags);
 	return 1;
 }
-
-/*
- * Helper routines for rw semaphores.  These could be optimized some
- * more, but since they're off the critical path, I prefer clarity for
- * now...
- */
-
-/*
- * This gets called if we failed to acquire the lock, but we're biased
- * to acquire the lock by virtue of causing the count to change from 0
- * to -1.  Being biased, we sleep and attempt to grab the lock until
- * we succeed.  When this function returns, we own the lock.
- */
-static inline void
-down_read_failed_biased (struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->read_bias_granted)
-			schedule();
-	}
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/*
- * This gets called if we failed to acquire the lock and we are not
- * biased to acquire the lock.  We undo the decrement that was
- * done earlier, go to sleep, and then attempt to re-acquire the
- * lock afterwards.
- */
-static inline void
-down_read_failed (struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	/*
-	 * Undo the decrement we did in down_read() and check if we
-	 * need to wake up someone.
-	 */
-	__up_read(sem);
-
-	add_wait_queue(&sem->wait, &wait);
-	while (sem->count < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->count >= 0)
-			break;
-		schedule();
-	}
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/*
- * Wait for the lock to become unbiased.  Readers are non-exclusive.
- */
-void
-__down_read_failed (struct rw_semaphore *sem, long count)
-{
-	while (1) {
-		if (count == -1) {
-			down_read_failed_biased(sem);
-			return;
-		}
-		/* unbiased */
-		down_read_failed(sem);
-
-		count = ia64_fetch_and_add(-1, &sem->count);
-		if (count >= 0)
-			return;
-	}
-}
-
-static inline void
-down_write_failed_biased (struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	/* put ourselves at the end of the list */
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/*
-	 * If the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (sem->count >= 0)
-		wake_up(&sem->wait);
-}
-
-
-static inline void
-down_write_failed (struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	__up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (sem->count < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->count >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-
-/*
- * Wait for the lock to become unbiased.  Since we're a writer, we'll
- * make ourselves exclusive.
- */
-void
-__down_write_failed (struct rw_semaphore *sem, long count)
-{
-	long old_count;
-
-	while (1) {
-		if (count == -RW_LOCK_BIAS) {
-			down_write_failed_biased(sem);
-			return;
-		}
-		down_write_failed(sem);
-
-		do {
-			old_count = sem->count;
-			count = old_count - RW_LOCK_BIAS;
-		} while (cmpxchg_acq(&sem->count, old_count, count) != old_count);
-
-		if (count == 0)
-			return;
-	}
-}
-
-void
-__rwsem_wake (struct rw_semaphore *sem, long count)
-{
-	wait_queue_head_t *wq;
-
-	if (count == 0) {
-		/* wake a writer */
-		if (xchg(&sem->write_bias_granted, 1))
-			BUG();
-		wq = &sem->write_bias_wait;
-	} else {
-		/* wake reader(s) */
-		if (xchg(&sem->read_bias_granted, 1))
-			BUG();
-		wq = &sem->wait;
-	}
-	wake_up(wq);	/* wake up everyone on the wait queue */
-}
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/setup.c linux/arch/ia64/kernel/setup.c
--- v2.4.3/linux/arch/ia64/kernel/setup.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/setup.c	Thu Apr  5 12:51:47 2001
@@ -1,8 +1,8 @@
 /*
  * Architecture-specific setup.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
  * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com>
  * Copyright (C) 1999 VA Linux Systems
@@ -42,16 +42,20 @@
 # include <linux/blk.h>
 #endif
 
+#if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)
+# error "struct cpuinfo_ia64 too big!"
+#endif
+
 extern char _end;
 
 /* cpu_data[0] is data for the bootstrap processor: */
-struct cpuinfo_ia64 cpu_data[NR_CPUS];
+struct cpuinfo_ia64 cpu_data[NR_CPUS] __attribute__ ((section ("__special_page_section")));
 
 unsigned long ia64_cycles_per_usec;
-struct ia64_boot_param ia64_boot_param;
+struct ia64_boot_param *ia64_boot_param;
 struct screen_info screen_info;
 /* This tells _start which CPU is booting.  */
-int cpu_now_booting = 0;
+int cpu_now_booting;
 
 #ifdef CONFIG_SMP
 volatile unsigned long cpu_online_map;
@@ -119,14 +123,7 @@
 
 	unw_init();
 
-	/*
-	 * The secondary bootstrap loader passes us the boot
-	 * parameters at the beginning of the ZERO_PAGE, so let's
-	 * stash away those values before ZERO_PAGE gets cleared out.
-	 */
-	memcpy(&ia64_boot_param, (void *) ZERO_PAGE_ADDR, sizeof(ia64_boot_param));
-
-	*cmdline_p = __va(ia64_boot_param.command_line);
+	*cmdline_p = __va(ia64_boot_param->command_line);
 	strncpy(saved_command_line, *cmdline_p, sizeof(saved_command_line));
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';		/* for safety */
 
@@ -140,9 +137,8 @@
 	 * change APIs, they'd do things for the better.  Grumble...
 	 */
 	bootmap_start = PAGE_ALIGN(__pa(&_end));
-	if (ia64_boot_param.initrd_size)
-		bootmap_start = PAGE_ALIGN(bootmap_start
-					   + ia64_boot_param.initrd_size);
+	if (ia64_boot_param->initrd_size)
+		bootmap_start = PAGE_ALIGN(bootmap_start + ia64_boot_param->initrd_size);
 	bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn);
 
 	efi_memmap_walk(free_available_memory, 0);
@@ -150,7 +146,7 @@
 	reserve_bootmem(bootmap_start, bootmap_size);
 
 #ifdef CONFIG_BLK_DEV_INITRD
-	initrd_start = ia64_boot_param.initrd_start;
+	initrd_start = ia64_boot_param->initrd_start;
 
 	if (initrd_start) {
 		u64 start, size;
@@ -163,16 +159,16 @@
 			       "for initrd, please upgrade the loader\n");
 		else
 #endif
-			/* 
+			/*
 			 * The loader ONLY passes physical addresses
 			 */
 			initrd_start = (unsigned long)__va(initrd_start);
-		initrd_end = initrd_start+ia64_boot_param.initrd_size;
+		initrd_end = initrd_start+ia64_boot_param->initrd_size;
 		start      = initrd_start;
-		size       = ia64_boot_param.initrd_size;
+		size       = ia64_boot_param->initrd_size;
 
 		printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
-		       (void *) initrd_start, ia64_boot_param.initrd_size);
+		       (void *) initrd_start, ia64_boot_param->initrd_size);
 
 		/*
 		 * The kernel end and the beginning of initrd can be
@@ -218,19 +214,19 @@
 	/* process SAL system table: */
 	ia64_sal_init(efi.sal_systab);
 
-#ifdef CONFIG_SMP
-	current->processor = 0;
-	cpu_physical_id(0) = hard_smp_processor_id();
-#endif
 	/*
 	 *  Set `iobase' to the appropriate address in region 6
 	 *    (uncached access range)
 	 */
-	__asm__ ("mov %0=ar.k0;;" : "=r"(ia64_iobase));
+	ia64_iobase = ia64_get_kr(IA64_KR_IO_BASE);
 	ia64_iobase = __IA64_UNCACHED_OFFSET | (ia64_iobase & ~PAGE_OFFSET);
 
 	cpu_init();	/* initialize the bootstrap CPU */
 
+#ifdef CONFIG_SMP
+	cpu_physical_id(0) = hard_smp_processor_id();
+#endif
+
 #ifdef CONFIG_IA64_GENERIC
 	machvec_init(acpi_get_sysname());
 #endif
@@ -239,7 +235,7 @@
 	if (efi.acpi20) {
 		/* Parse the ACPI 2.0 tables */
 		acpi20_parse(efi.acpi20);
-	} else 
+	} else
 #endif
 	if (efi.acpi) {
 		/* Parse the ACPI tables */
@@ -259,8 +255,8 @@
 	ia64_mca_init();
 #endif
 
-	paging_init();
 	platform_setup(cmdline_p);
+	paging_init();
 }
 
 /*
@@ -325,7 +321,7 @@
 			     c->ppn, c->number, c->proc_freq / 1000000, c->proc_freq % 1000000,
 			     c->itc_freq / 1000000, c->itc_freq % 1000000,
 			     lpj*HZ/500000, (lpj*HZ/5000) % 100);
-        }
+	}
 	return p - buffer;
 }
 
@@ -362,8 +358,6 @@
 	for (i = 0; i < 5; ++i)
 		cpuid.bits[i] = ia64_get_cpuid(i);
 
-	memset(c, 0, sizeof(struct cpuinfo_ia64));
-
 	memcpy(c->vendor, cpuid.field.vendor, 16);
 	c->ppn = cpuid.field.ppn;
 	c->number = cpuid.field.number;
@@ -382,12 +376,6 @@
 	       smp_processor_id(), impl_va_msb + 1, phys_addr_size);
 	c->unimpl_va_mask = ~((7L<<61) | ((1L << (impl_va_msb + 1)) - 1));
 	c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1));
-
-#ifdef CONFIG_IA64_SOFTSDV_HACKS
-	/* BUG: SoftSDV doesn't support the cpuid registers. */
-	if (c->vendor[0] == '\0') 
-		memcpy(c->vendor, "Intel", 6);
-#endif
 }
 
 /*
@@ -397,12 +385,18 @@
 void
 cpu_init (void)
 {
-	extern void __init ia64_rid_init (void);
-	extern void __init ia64_tlb_init (void);
+	extern void __init ia64_mmu_init (void);
+	unsigned long num_phys_stacked;
 	pal_vm_info_2_u_t vmi;
 	unsigned int max_ctx;
 
-	identify_cpu(&my_cpu_data);
+	/*
+	 * We can't pass "local_cpu_data" do identify_cpu() because we haven't called
+	 * ia64_mmu_init() yet.  And we can't call ia64_mmu_init() first because it
+	 * depends on the data returned by identify_cpu().  We break the dependency by
+	 * accessing cpu_data[] the old way, through identity mapped space.
+	 */
+	identify_cpu(&cpu_data[smp_processor_id()]);
 
 	/* Clear the stack memory reserved for pt_regs: */
 	memset(ia64_task_regs(current), 0, sizeof(struct pt_regs));
@@ -415,22 +409,30 @@
 	ia64_set_dcr(  IA64_DCR_DM | IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_DR
 		     | IA64_DCR_DA | IA64_DCR_DD);
 #ifndef CONFIG_SMP
-	ia64_set_fpu_owner(0);		/* initialize ar.k5 */
+	ia64_set_fpu_owner(0);
 #endif
 
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
 
-	ia64_rid_init();
-	ia64_tlb_init();
+	ia64_mmu_init();
 
-#ifdef	CONFIG_IA32_SUPPORT
+#ifdef CONFIG_IA32_SUPPORT
 	/* initialize global ia32 state - CR0 and CR4 */
 	__asm__("mov ar.cflg = %0"
 		: /* no outputs */
 		: "r" (((ulong) IA32_CR4 << 32) | IA32_CR0));
 #endif
 
+	/* disable all local interrupt sources: */
+	ia64_set_itv(1 << 16);
+	ia64_set_lrr0(1 << 16);
+	ia64_set_lrr1(1 << 16);
+	ia64_set_pmv(1 << 16);
+	ia64_set_cmcv(1 << 16);
+
+	/* clear TPR & XTP to enable all interrupt classes: */
+	ia64_set_tpr(0);
 #ifdef CONFIG_SMP
 	normal_xtp();
 #endif
@@ -439,7 +441,7 @@
 	if (ia64_pal_vm_summary(NULL, &vmi) == 0)
 		max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1;
 	else {
-		printk("ia64_rid_init: PAL VM summary failed, assuming 18 RID bits\n");
+		printk("cpu_init: PAL VM summary failed, assuming 18 RID bits\n");
 		max_ctx = (1U << 15) - 1;	/* use architected minimum */
 	}
 	while (max_ctx < ia64_ctx.max_ctx) {
@@ -447,4 +449,10 @@
 		if (cmpxchg(&ia64_ctx.max_ctx, old, max_ctx) == old)
 			break;
 	}
+
+	if (ia64_pal_rse_info(&num_phys_stacked, 0) != 0) {
+		printk ("cpu_init: PAL RSE info failed, assuming 96 physical stacked regs\n");
+		num_phys_stacked = 96;
+	}
+	local_cpu_data->phys_stacked_size_p8 = num_phys_stacked*8 + 8;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/signal.c linux/arch/ia64/kernel/signal.c
--- v2.4.3/linux/arch/ia64/kernel/signal.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/signal.c	Thu Apr  5 12:51:47 2001
@@ -1,8 +1,8 @@
 /*
  * Architecture-specific signal handling support.
  *
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Derived from i386 and Alpha versions.
  */
@@ -38,12 +38,8 @@
 #endif
 
 struct sigscratch {
-#ifdef CONFIG_IA64_NEW_UNWIND
 	unsigned long scratch_unat;	/* ar.unat for the general registers saved in pt */
 	unsigned long pad;
-#else
-	struct switch_stack sw;
-#endif
 	struct pt_regs pt;
 };
 
@@ -52,7 +48,6 @@
 	struct sigcontext sc;
 };
 
-extern long sys_wait4 (int, int *, int, struct rusage *);
 extern long ia64_do_signal (sigset_t *, struct sigscratch *, long);	/* forward decl */
 
 long
@@ -141,11 +136,7 @@
 	ia64_psr(&scr->pt)->ri = ip & 0x3;
 	scr->pt.cr_ipsr = (scr->pt.cr_ipsr & ~IA64_PSR_UM) | (um & IA64_PSR_UM);
 
-#ifdef CONFIG_IA64_NEW_UNWIND
 	scr->scratch_unat = ia64_put_scratch_nat_bits(&scr->pt, nat);
-#else
-	ia64_put_nat_bits(&scr->pt, &scr->sw, nat);	/* restore the original scratch NaT bits */
-#endif
 
 	if ((flags & IA64_SC_FLAG_FPH_VALID) != 0) {
 		struct ia64_psr *psr = ia64_psr(&scr->pt);
@@ -162,7 +153,7 @@
 int
 copy_siginfo_to_user (siginfo_t *to, siginfo_t *from)
 {
-	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
+	if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t)))
 		return -EFAULT;
 	if (from->si_code < 0)
 		return __copy_to_user(to, from, sizeof(siginfo_t));
@@ -190,6 +181,11 @@
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
 			err |= __put_user(from->si_status, &to->si_status);
+		      case __SI_PROF >> 16:
+			err |= __put_user(from->si_uid, &to->si_uid);
+			err |= __put_user(from->si_pid, &to->si_pid);
+			err |= __put_user(from->si_pfm_ovfl, &to->si_pfm_ovfl);
+			break;
 		      default:
 			err |= __put_user(from->si_uid, &to->si_uid);
 			err |= __put_user(from->si_pid, &to->si_pid);
@@ -200,6 +196,43 @@
 	}
 }
 
+int
+copy_siginfo_from_user (siginfo_t *to, siginfo_t *from)
+{
+	if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t)))
+		return -EFAULT;
+	if (__copy_from_user(to, from, sizeof(siginfo_t)) != 0)
+		return -EFAULT;
+
+	if (SI_FROMUSER(to))
+		return 0;
+
+	to->si_code &= ~__SI_MASK;
+	if (to->si_code != 0) {
+		switch (to->si_signo) {
+		      case SIGILL: case SIGFPE: case SIGSEGV: case SIGBUS: case SIGTRAP:
+			to->si_code |= __SI_FAULT;
+			break;
+
+		      case SIGCHLD:
+			to->si_code |= __SI_CHLD;
+			break;
+
+		      case SIGPOLL:
+			to->si_code |= __SI_POLL;
+			break;
+
+		      case SIGPROF:
+			to->si_code |= __SI_PROF;
+			break;
+
+		      default:
+			break;
+		}
+	}
+	return 0;
+}
+
 long
 ia64_rt_sigreturn (struct sigscratch *scr)
 {
@@ -212,19 +245,17 @@
 	sc = &((struct sigframe *) (scr->pt.r12 + 16))->sc;
 
 	/*
-	 * When we return to the previously executing context, r8 and
-	 * r10 have already been setup the way we want them.  Indeed,
-	 * if the signal wasn't delivered while in a system call, we
-	 * must not touch r8 or r10 as otherwise user-level stat could
-	 * be corrupted.
+	 * When we return to the previously executing context, r8 and r10 have already
+	 * been setup the way we want them.  Indeed, if the signal wasn't delivered while
+	 * in a system call, we must not touch r8 or r10 as otherwise user-level state
+	 * could be corrupted.
 	 */
 	retval = (long) &ia64_leave_kernel;
 	if (current->ptrace & PT_TRACESYS)
 		/*
-		 * strace expects to be notified after sigreturn
-		 * returns even though the context to which we return
-		 * may not be in the middle of a syscall.  Thus, the
-		 * return-value that strace displays for sigreturn is
+		 * strace expects to be notified after sigreturn returns even though the
+		 * context to which we return may not be in the middle of a syscall.
+		 * Thus, the return-value that strace displays for sigreturn is
 		 * meaningless.
 		 */
 		retval = (long) &ia64_strace_leave_kernel;
@@ -301,11 +332,7 @@
 	 * preserved registers (r4-r7) are never being looked at by
 	 * the signal handler (registers r4-r7 are used instead).
 	 */
-#ifdef CONFIG_IA64_NEW_UNWIND
 	nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat);
-#else
-	nat = ia64_get_nat_bits(&scr->pt, &scr->sw);
-#endif
 
 	err  = __put_user(flags, &sc->sc_flags);
 
@@ -371,21 +398,11 @@
 	scr->pt.cr_iip = tramp_addr;
 	ia64_psr(&scr->pt)->ri = 0;			/* start executing in first slot */
 
-#ifdef CONFIG_IA64_NEW_UNWIND
 	/*
 	 * Note: this affects only the NaT bits of the scratch regs
 	 * (the ones saved in pt_regs), which is exactly what we want.
 	 */
 	scr->scratch_unat = 0; /* ensure NaT bits of at least r2, r3, r12, and r15 are clear */
-#else
-	/*
-	 * Note: this affects only the NaT bits of the scratch regs
-	 * (the ones saved in pt_regs), which is exactly what we want.
-	 * The NaT bits for the preserved regs (r4-r7) are in
-	 * sw->ar_unat iff this process is being PTRACED.
-	 */
-	scr->sw.caller_unat = 0; /* ensure NaT bits of at least r2, r3, r12, and r15 are clear */
-#endif
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%lx\n",
@@ -437,13 +454,8 @@
 }
 
 /*
- * Note that `init' is a special process: it doesn't get signals it
- * doesn't want to handle.  Thus you cannot kill init even with a
- * SIGKILL even by mistake.
- *
- * Note that we go through the signals twice: once to check the
- * signals that the kernel can handle, and then we build all the
- * user-level signal handling stack-frames in one go after that.
+ * Note that `init' is a special process: it doesn't get signals it doesn't want to
+ * handle.  Thus you cannot kill init even with a SIGKILL even by mistake.
  */
 long
 ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
@@ -454,9 +466,9 @@
 	long errno = scr->pt.r8;
 
 	/*
-	 * In the ia64_leave_kernel code path, we want the common case
-	 * to go fast, which is why we may in certain cases get here
-	 * from kernel mode. Just return without doing anything if so.
+	 * In the ia64_leave_kernel code path, we want the common case to go fast, which
+	 * is why we may in certain cases get here from kernel mode. Just return without
+	 * doing anything if so.
 	 */
 	if (!user_mode(&scr->pt))
 		return 0;
@@ -476,11 +488,10 @@
 #endif
 	if (scr->pt.r10 != -1) {
 		/*
-		 * A system calls has to be restarted only if one of
-		 * the error codes ERESTARTNOHAND, ERESTARTSYS, or
-		 * ERESTARTNOINTR is returned.  If r10 isn't -1 then
-		 * r8 doesn't hold an error code and we don't need to
-		 * restart the syscall, so we set in_syscall to zero.
+		 * A system calls has to be restarted only if one of the error codes
+		 * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned.  If r10
+		 * isn't -1 then r8 doesn't hold an error code and we don't need to
+		 * restart the syscall, so we can clear the "restart" flag here.
 		 */
 		restart = 0;
 	}
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/smp.c linux/arch/ia64/kernel/smp.c
--- v2.4.3/linux/arch/ia64/kernel/smp.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/smp.c	Thu Apr  5 12:51:47 2001
@@ -2,8 +2,8 @@
  * SMP Support
  *
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- * 
+ * Copyright (C) 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
  * Lots of stuff stolen from arch/alpha/kernel/smp.c
  *
  *  00/09/11 David Mosberger <davidm@hpl.hp.com> Do loops_per_jiffy calibration on each CPU.
@@ -37,8 +37,8 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/page.h>
-#include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/sal.h>
@@ -50,9 +50,8 @@
 extern void machine_halt(void);
 extern void start_ap(void);
 
-extern int cpu_now_booting;			     /* Used by head.S to find idle task */
-extern volatile unsigned long cpu_online_map;	     /* Bitmap of available cpu's */
-extern struct cpuinfo_ia64 cpu_data[NR_CPUS];	     /* Duh... */
+extern int cpu_now_booting;			/* used by head.S to find idle task */
+extern volatile unsigned long cpu_online_map;	/* bitmap of available cpu's */
 
 struct smp_boot_data smp_boot_data __initdata;
 
@@ -60,18 +59,19 @@
 
 char __initdata no_int_routing;
 
+/* don't make this a CPU-local variable: it's used for IPIs, mostly...  */
+int __cpu_physical_id[NR_CPUS];			/* logical ID -> physical CPU ID map */
+
 unsigned char smp_int_redirect;			/* are INT and IPI redirectable by the chipset? */
-volatile int __cpu_physical_id[NR_CPUS] = { -1, };    /* Logical ID -> SAPIC ID */
-int smp_num_cpus = 1;		
-volatile int smp_threads_ready;			     /* Set when the idlers are all forked */
-cycles_t cacheflush_time;
-unsigned long ap_wakeup_vector = -1;		     /* External Int to use to wakeup AP's */
+int smp_num_cpus = 1;
+volatile int smp_threads_ready;			/* set when the idlers are all forked */
+unsigned long ap_wakeup_vector;			/* external Int to use to wakeup AP's */
 
 static volatile unsigned long cpu_callin_map;
 static volatile int smp_commenced;
 
-static int max_cpus = -1;			     /* Command line */
-static unsigned long ipi_op[NR_CPUS];
+static int max_cpus = -1;			/* command line */
+
 struct smp_call_struct {
 	void (*func) (void *info);
 	void *info;
@@ -99,7 +99,8 @@
  *	SMP mode to <NUM>.
  */
 
-static int __init nosmp(char *str)
+static int __init
+nosmp (char *str)
 {
 	max_cpus = 0;
 	return 1;
@@ -107,7 +108,8 @@
 
 __setup("nosmp", nosmp);
 
-static int __init maxcpus(char *str)
+static int __init
+maxcpus (char *str)
 {
 	get_option(&str, &max_cpus);
 	return 1;
@@ -116,7 +118,7 @@
 __setup("maxcpus=", maxcpus);
 
 static int __init
-nointroute(char *str)
+nointroute (char *str)
 {
 	no_int_routing = 1;
 	return 1;
@@ -125,21 +127,20 @@
 __setup("nointroute", nointroute);
 
 /*
- * Yoink this CPU from the runnable list... 
+ * Yoink this CPU from the runnable list...
  */
 void
-halt_processor(void) 
+halt_processor (void)
 {
-        clear_bit(smp_processor_id(), &cpu_online_map);
+	clear_bit(smp_processor_id(), &cpu_online_map);
 	max_xtp();
 	__cli();
-        for (;;)
+	for (;;)
 		;
-
 }
 
 static inline int
-pointer_lock(void *lock, void *data, int retry)
+pointer_lock (void *lock, void *data, int retry)
 {
 	volatile long *ptr = lock;
  again:
@@ -156,14 +157,13 @@
 }
 
 void
-handle_IPI(int irq, void *dev_id, struct pt_regs *regs) 
+handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
 {
-	int this_cpu = smp_processor_id();
-	unsigned long *pending_ipis = &ipi_op[this_cpu];
+	unsigned long *pending_ipis = &local_cpu_data->ipi_operation;
 	unsigned long ops;
 
 	/* Count this now; we may make a call that never returns. */
-	cpu_data[this_cpu].ipi_count++;
+	local_cpu_data->ipi_count++;
 
 	mb();	/* Order interrupt and bit testing. */
 	while ((ops = xchg(pending_ipis, 0)) != 0) {
@@ -173,16 +173,16 @@
 
 		which = ffz(~ops);
 		ops &= ~(1 << which);
-		
+
 		switch (which) {
 		case IPI_RESCHEDULE:
-			/* 
-			 * Reschedule callback.  Everything to be done is done by the 
-			 * interrupt return path.  
+			/*
+			 * Reschedule callback.  Everything to be done is done by the
+			 * interrupt return path.
 			 */
 			break;
-			
-		case IPI_CALL_FUNC: 
+
+		case IPI_CALL_FUNC:
 			{
 				struct smp_call_struct *data;
 				void (*func)(void *info);
@@ -203,7 +203,7 @@
 
 				/* Notify the sending CPU that the task is done.  */
 				mb();
-				if (wait) 
+				if (wait)
 					atomic_dec(&data->unfinished_count);
 			}
 			break;
@@ -214,7 +214,7 @@
 
 #ifndef CONFIG_ITANIUM_PTCG
 		case IPI_FLUSH_TLB:
-                {
+		{
 			extern unsigned long flush_start, flush_end, flush_nbits, flush_rid;
 			extern atomic_t flush_cpu_count;
 			unsigned long saved_rid = ia64_get_rr(flush_start);
@@ -223,6 +223,8 @@
 			unsigned long nbits = flush_nbits;
 
 			/*
+			 * Current CPU may be running with different RID so we need to
+			 * reload the RID of flushed address.
 			 * Current CPU may be running with different
 			 * RID so we need to reload the RID of flushed
 			 * address.  Purging the translation also
@@ -235,7 +237,7 @@
 				ia64_set_rr(flush_start, flush_rid);
 				ia64_srlz_d();
 			}
-			
+
 			do {
 				/*
 				 * Purge local TLB entries.
@@ -258,7 +260,8 @@
 #endif	/* !CONFIG_ITANIUM_PTCG */
 
 		default:
-			printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
+			printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
+			       smp_processor_id(), which);
 			break;
 		} /* Switch */
 	  } while (ops);
@@ -268,21 +271,21 @@
 }
 
 static inline void
-send_IPI_single (int dest_cpu, int op) 
+send_IPI_single (int dest_cpu, int op)
 {
-	
-	if (dest_cpu == -1) 
-                return;
-        
-	set_bit(op, &ipi_op[dest_cpu]);
-	platform_send_ipi(dest_cpu, IPI_IRQ, IA64_IPI_DM_INT, 0);
+
+	if (dest_cpu == -1)
+		return;
+
+	set_bit(op, &cpu_data[dest_cpu].ipi_operation);
+	platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
 }
 
 static inline void
-send_IPI_allbutself(int op)
+send_IPI_allbutself (int op)
 {
 	int i;
-	
+
 	for (i = 0; i < smp_num_cpus; i++) {
 		if (i != smp_processor_id())
 			send_IPI_single(i, op);
@@ -290,7 +293,7 @@
 }
 
 static inline void
-send_IPI_all(int op)
+send_IPI_all (int op)
 {
 	int i;
 
@@ -299,30 +302,42 @@
 }
 
 static inline void
-send_IPI_self(int op)
+send_IPI_self (int op)
 {
 	send_IPI_single(smp_processor_id(), op);
 }
 
 void
-smp_send_reschedule(int cpu)
+smp_send_reschedule (int cpu)
 {
 	send_IPI_single(cpu, IPI_RESCHEDULE);
 }
 
 void
-smp_send_stop(void)
+smp_send_stop (void)
 {
 	send_IPI_allbutself(IPI_CPU_STOP);
 }
 
 #ifndef CONFIG_ITANIUM_PTCG
+
 void
-smp_send_flush_tlb(void)
+smp_send_flush_tlb (void)
 {
 	send_IPI_allbutself(IPI_FLUSH_TLB);
 }
-#endif	/* !CONFIG_ITANIUM_PTCG */
+
+void
+smp_resend_flush_tlb(void)
+{
+	/*
+	 * Really need a null IPI but since this rarely should happen & since this code
+	 * will go away, lets not add one.
+	 */
+	send_IPI_allbutself(IPI_RESCHEDULE);
+}
+
+#endif /* !CONFIG_ITANIUM_PTCG */
 
 /*
  * Run a function on another CPU
@@ -347,7 +362,7 @@
 		printk(__FUNCTION__" trying to call self\n");
 		return -EBUSY;
 	}
-	
+
 	data.func = func;
 	data.info = info;
 	data.wait = wait;
@@ -392,7 +407,6 @@
  * Does not return until remote CPUs are nearly ready to execute <func>
  * or are or have executed.
  */
-
 int
 smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
 {
@@ -402,7 +416,7 @@
 
 	if (cpus == 0)
 		return 0;
-	
+
 	data.func = func;
 	data.info = info;
 	data.wait = wait;
@@ -425,7 +439,7 @@
 		int i;
 		for (i = 0; i < smp_num_cpus; i++) {
 			if (i != smp_processor_id())
-				platform_send_ipi(i, IPI_IRQ, IA64_IPI_DM_INT, 0);
+				platform_send_ipi(i, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
 		}
 		goto retry;
 #else
@@ -446,7 +460,7 @@
  * want to ensure all TLB's flushed before proceeding.
  */
 void
-smp_flush_tlb_all(void)
+smp_flush_tlb_all (void)
 {
 	smp_call_function((void (*)(void *))__flush_tlb_all, NULL, 1, 1);
 	__flush_tlb_all();
@@ -456,21 +470,19 @@
  * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
  */
 static inline void __init
-smp_setup_percpu_timer(int cpuid)
+smp_setup_percpu_timer(void)
 {
-        cpu_data[cpuid].prof_counter = 1;
-        cpu_data[cpuid].prof_multiplier = 1;
+	local_cpu_data->prof_counter = 1;
+	local_cpu_data->prof_multiplier = 1;
 }
 
-void 
-smp_do_timer(struct pt_regs *regs)
+void
+smp_do_timer (struct pt_regs *regs)
 {
-        int cpu = smp_processor_id();
-        int user = user_mode(regs);
-	struct cpuinfo_ia64 *data = &cpu_data[cpu];
+	int user = user_mode(regs);
 
-        if (--data->prof_counter <= 0) {
-		data->prof_counter = data->prof_multiplier;
+	if (--local_cpu_data->prof_counter <= 0) {
+		local_cpu_data->prof_counter = local_cpu_data->prof_multiplier;
 		update_process_times(user);
 	}
 }
@@ -480,7 +492,7 @@
  * AP's start using C here.
  */
 void __init
-smp_callin (void) 
+smp_callin (void)
 {
 	extern void ia64_rid_init(void);
 	extern void ia64_init_itm(void);
@@ -493,12 +505,12 @@
 	if (test_and_set_bit(cpu, &cpu_online_map)) {
 		printk("CPU#%d already initialized!\n", cpu);
 		machine_halt();
-	}  
+	}
 
 	efi_map_pal_code();
 	cpu_init();
 
-	smp_setup_percpu_timer(cpu);
+	smp_setup_percpu_timer();
 
 	/* setup the CPU local timer tick */
 	ia64_init_itm();
@@ -506,15 +518,10 @@
 #ifdef CONFIG_PERFMON
 	perfmon_init_percpu();
 #endif
-
-	/* Disable all local interrupts */
-	ia64_set_lrr0(0, 1);	
-	ia64_set_lrr1(0, 1);	
-
 	local_irq_enable();		/* Interrupts have been off until now */
 
 	calibrate_delay();
-	my_cpu_data.loops_per_jiffy = loops_per_jiffy;
+	local_cpu_data->loops_per_jiffy = loops_per_jiffy;
 
 	/* allow the master to continue */
 	set_bit(cpu, &cpu_callin_map);
@@ -531,8 +538,8 @@
  * path in which case the new idle task could get scheduled before we
  * had a chance to remove it from the run-queue...
  */
-static int __init 
-fork_by_hand(void)
+static int __init
+fork_by_hand (void)
 {
 	/*
 	 * Don't care about the usp and regs settings since we'll never
@@ -545,22 +552,22 @@
  * Bring one cpu online.  Return 0 if this fails for any reason.
  */
 static int __init
-smp_boot_one_cpu(int cpu)
+smp_boot_one_cpu (int cpu)
 {
 	struct task_struct *idle;
 	int cpu_phys_id = cpu_physical_id(cpu);
 	long timeout;
 
-	/* 
+	/*
 	 * Create an idle task for this CPU.  Note that the address we
 	 * give to kernel_thread is irrelevant -- it's going to start
 	 * where OS_BOOT_RENDEVZ vector in SAL says to start.  But
 	 * this gets all the other task-y sort of data structures set
-	 * up like we wish.   We need to pull the just created idle task 
-	 * off the run queue and stuff it into the init_tasks[] array.  
+	 * up like we wish.   We need to pull the just created idle task
+	 * off the run queue and stuff it into the init_tasks[] array.
 	 * Sheesh . . .
 	 */
-	if (fork_by_hand() < 0) 
+	if (fork_by_hand() < 0)
 		panic("failed fork for CPU 0x%x", cpu_phys_id);
 	/*
 	 * We remove it from the pidhash and the runqueue
@@ -571,7 +578,7 @@
 		panic("No idle process for CPU 0x%x", cpu_phys_id);
 	init_tasks[cpu] = idle;
 	del_from_runqueue(idle);
-        unhash_process(idle);
+	unhash_process(idle);
 
 	/* Schedule the first task manually.  */
 	idle->processor = cpu;
@@ -590,50 +597,41 @@
 		udelay(100);
 	}
 
-	printk(KERN_ERR "SMP: Processor 0x%x is stuck.\n", cpu_phys_id);
+	printk(KERN_ERR "SMP: CPU 0x%x is stuck\n", cpu_phys_id);
 	return 0;
 }
 
 
 
 /*
- * Called by smp_init bring all the secondaries online and hold them.  
- * XXX: this is ACPI specific; it uses "magic" variables exported from acpi.c 
- *      to 'discover' the AP's.  Blech.
+ * Called by smp_init bring all the secondaries online and hold them.
  */
 void __init
-smp_boot_cpus(void)
+smp_boot_cpus (void)
 {
 	int i, cpu_count = 1;
 	unsigned long bogosum;
 
-	/* Take care of some initial bookkeeping.  */
-	memset(&__cpu_physical_id, -1, sizeof(__cpu_physical_id));
-	memset(&ipi_op, 0, sizeof(ipi_op));
-
-	/* Setup BP mappings */
-	__cpu_physical_id[0] = hard_smp_processor_id();
-
 	/* on the BP, the kernel already called calibrate_delay_loop() in init/main.c */
-	my_cpu_data.loops_per_jiffy = loops_per_jiffy;
+	local_cpu_data->loops_per_jiffy = loops_per_jiffy;
 #if 0
 	smp_tune_scheduling();
 #endif
- 	smp_setup_percpu_timer(0);
+	smp_setup_percpu_timer();
 
 	if (test_and_set_bit(0, &cpu_online_map)) {
 		printk("CPU#%d already initialized!\n", smp_processor_id());
 		machine_halt();
-	}  
+	}
 	init_idle();
 
 	/* Nothing to do when told not to.  */
 	if (max_cpus == 0) {
-	        printk(KERN_INFO "SMP mode deactivated.\n");
+		printk(KERN_INFO "SMP mode deactivated.\n");
 		return;
 	}
 
-	if (max_cpus != -1) 
+	if (max_cpus != -1)
 		printk("Limiting CPUs to %d\n", max_cpus);
 
 	if (smp_boot_data.cpu_count > 1) {
@@ -650,7 +648,7 @@
 				continue;	/* failed */
 
 			cpu_count++; /* Count good CPUs only... */
-			/* 
+			/*
 			 * Bail if we've started as many CPUS as we've been told to.
 			 */
 			if (cpu_count == max_cpus)
@@ -663,10 +661,10 @@
 	}
 
 	bogosum = 0;
-        for (i = 0; i < NR_CPUS; i++) {
+	for (i = 0; i < NR_CPUS; i++) {
 		if (cpu_online_map & (1L << i))
 			bogosum += cpu_data[i].loops_per_jiffy;
-        }
+	}
 
 	printk(KERN_INFO "SMP: Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
 	       cpu_count, bogosum*HZ/500000, (bogosum*HZ/5000) % 100);
@@ -674,31 +672,31 @@
 	smp_num_cpus = cpu_count;
 }
 
-/* 
+/*
  * Called when the BP is just about to fire off init.
  */
-void __init 
-smp_commence(void)
+void __init
+smp_commence (void)
 {
 	smp_commenced = 1;
 }
 
 int __init
-setup_profiling_timer(unsigned int multiplier)
+setup_profiling_timer (unsigned int multiplier)
 {
-        return -EINVAL;
+	return -EINVAL;
 }
 
 /*
  * Assume that CPU's have been discovered by some platform-dependant
  * interface.  For SoftSDV/Lion, that would be ACPI.
  *
- * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP().
+ * Setup of the IPI irq handler is done in irq.c:init_IRQ().
  *
  * This also registers the AP OS_MC_REDVEZ address with SAL.
  */
 void __init
-init_smp_config(void)
+init_smp_config (void)
 {
 	struct fptr {
 		unsigned long fp;
@@ -708,14 +706,13 @@
 
 	/* Tell SAL where to drop the AP's.  */
 	ap_startup = (struct fptr *) start_ap;
-	sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,
-				       __pa(ap_startup->fp), __pa(ap_startup->gp), 0, 
-				       0, 0, 0);
+	sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ, __pa(ap_startup->fp),
+				       __pa(ap_startup->gp), 0, 0, 0, 0);
 	if (sal_ret < 0) {
 		printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n", ia64_sal_strerror(sal_ret));
 		printk("     Forcing UP mode\n");
 		max_cpus = 0;
-		smp_num_cpus = 1; 
+		smp_num_cpus = 1;
 	}
 
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/smpboot.c linux/arch/ia64/kernel/smpboot.c
--- v2.4.3/linux/arch/ia64/kernel/smpboot.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/kernel/smpboot.c	Thu Apr  5 12:51:47 2001
@@ -1,74 +1,4 @@
 /*
- * SMP Support
- *
- * Application processor startup code, moved from smp.c to better support kernel profile
  */
 
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
-#include <linux/kernel_stat.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#include <asm/atomic.h>
-#include <asm/bitops.h>
-#include <asm/current.h>
-#include <asm/delay.h>
-#include <asm/efi.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/pgalloc.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/sal.h>
-#include <asm/system.h>
-#include <asm/unistd.h>
-
-/* 
- * SAL shoves the AP's here when we start them.  Physical mode, no kernel TR, 
- * no RRs set, better than even chance that psr is bogus.  Fix all that and 
- * call _start.  In effect, pretend to be lilo.
- *
- * Stolen from lilo_start.c.  Thanks David! 
- */
-void
-start_ap(void)
-{
-	extern void _start (void);
-	unsigned long flags;
-
-	/*
-	 * Install a translation register that identity maps the
-	 * kernel's 256MB page(s).
-	 */
-	ia64_clear_ic(flags);
-	ia64_set_rr(          0, (0x1000 << 8) | (_PAGE_SIZE_1M << 2));
-	ia64_set_rr(PAGE_OFFSET, (ia64_rid(0, PAGE_OFFSET) << 8) | (_PAGE_SIZE_256M << 2));
-	ia64_srlz_d();
-	ia64_itr(0x3, 1, PAGE_OFFSET,
-		 pte_val(mk_pte_phys(0, __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX))),
-		 _PAGE_SIZE_256M);
-	ia64_srlz_i();
-
-	flags = (IA64_PSR_IT | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_DFH | 
-		 IA64_PSR_BN);
-	
-	asm volatile ("movl r8 = 1f\n"
-		      ";;\n"
-		      "mov cr.ipsr=%0\n"
-		      "mov cr.iip=r8\n" 
-		      "mov cr.ifs=r0\n"
-		      ";;\n"
-		      "rfi;;"
-		      "1:\n"
-		      "movl r1 = __gp" :: "r"(flags) : "r8");
-	_start();
-}
-
-
+/* place holder... */
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/sys_ia64.c linux/arch/ia64/kernel/sys_ia64.c
--- v2.4.3/linux/arch/ia64/kernel/sys_ia64.c	Mon Mar 19 12:35:10 2001
+++ linux/arch/ia64/kernel/sys_ia64.c	Fri Apr 13 15:38:51 2001
@@ -22,16 +22,16 @@
 #define COLOR_ALIGN(addr)	(((addr) + SHMLBA - 1) & ~(SHMLBA - 1))
 
 unsigned long
-get_unmapped_area (unsigned long addr, unsigned long len)
+arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
 	struct vm_area_struct * vmm;
 
 	if (len > RGN_MAP_LIMIT)
-		return 0;
+		return -ENOMEM;
 	if (!addr)
 		addr = TASK_UNMAPPED_BASE;
 
-	if (current->thread.flags & IA64_THREAD_MAP_SHARED)
+	if (flags & MAP_SHARED)
 		addr = COLOR_ALIGN(addr);
 	else
 		addr = PAGE_ALIGN(addr);
@@ -39,17 +39,19 @@
 	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
 		/* At this point:  (!vmm || addr < vmm->vm_end). */
 		if (TASK_SIZE - len < addr)
-			return 0;
+			return -ENOMEM;
 		if (rgn_offset(addr) + len > RGN_MAP_LIMIT)	/* no risk of overflow here... */
-			return 0;
+			return -ENOMEM;
 		if (!vmm || addr + len <= vmm->vm_start)
 			return addr;
 		addr = vmm->vm_end;
+		if (flags & MAP_SHARED)
+			addr = COLOR_ALIGN(addr);
 	}
 }
 
 asmlinkage long
-ia64_getpriority (int which, int who, long arg2, long arg3, long arg4, long arg5, long arg6, 
+ia64_getpriority (int which, int who, long arg2, long arg3, long arg4, long arg5, long arg6,
 		  long arg7, long stack)
 {
 	struct pt_regs *regs = (struct pt_regs *) &stack;
@@ -197,15 +199,10 @@
 			return -EBADF;
 	}
 
-	if (flags & MAP_SHARED)
-		current->thread.flags |= IA64_THREAD_MAP_SHARED;
-
 	down_write(&current->mm->mmap_sem);
 	addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
 
-	current->thread.flags &= ~IA64_THREAD_MAP_SHARED;
-
 	if (file)
 		fput(file);
 	return addr;
@@ -246,15 +243,15 @@
 asmlinkage long
 sys_vm86 (long arg0, long arg1, long arg2, long arg3)
 {
-        printk(KERN_ERR "sys_vm86(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3);
-        return -ENOSYS;
+	printk(KERN_ERR "sys_vm86(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3);
+	return -ENOSYS;
 }
 
 asmlinkage long
 sys_modify_ldt (long arg0, long arg1, long arg2, long arg3)
 {
-        printk(KERN_ERR "sys_modify_ldt(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3);
-        return -ENOSYS;
+	printk(KERN_ERR "sys_modify_ldt(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3);
+	return -ENOSYS;
 }
 
 asmlinkage unsigned long
@@ -392,7 +389,7 @@
 	}
 	return err;
 }
- 
+
 #endif
 
 #ifndef CONFIG_PCI
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/time.c linux/arch/ia64/kernel/time.c
--- v2.4.3/linux/arch/ia64/kernel/time.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/time.c	Thu Apr  5 12:51:47 2001
@@ -1,9 +1,9 @@
 /*
  * linux/arch/ia64/kernel/time.c
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
  * Copyright (C) 1998-2000 Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1999-2000 David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 David Mosberger <davidm@hpl.hp.com>
  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
  * Copyright (C) 1999-2000 VA Linux Systems
  * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com>
@@ -32,14 +32,6 @@
 
 #endif
 
-static struct {
-	unsigned long delta;
-	union {
-		unsigned long count;
-		unsigned char pad[SMP_CACHE_BYTES];
-	} next[NR_CPUS];
-} itm;
-
 static void
 do_profile (unsigned long ip)
 {
@@ -61,7 +53,7 @@
 			ip = prof_len - 1;
 
 		atomic_inc((atomic_t *) &prof_buffer[ip]);
-	} 
+	}
 }
 
 /*
@@ -82,7 +74,7 @@
 	unsigned long now = ia64_get_itc(), last_tick;
 	unsigned long elapsed_cycles, lost = jiffies - wall_jiffies;
 
-	last_tick = (itm.next[smp_processor_id()].count - (lost+1)*itm.delta);
+	last_tick = (local_cpu_data->itm_next - (lost+1)*local_cpu_data->itm_delta);
 # if 1
 	if ((long) (now - last_tick) < 0) {
 		printk("Yikes: now < last_tick (now=0x%lx,last_tick=%lx)!  No can do.\n",
@@ -91,7 +83,7 @@
 	}
 # endif
 	elapsed_cycles = now - last_tick;
-	return (elapsed_cycles*my_cpu_data.usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
+	return (elapsed_cycles*local_cpu_data->usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
 #endif
 }
 
@@ -132,7 +124,7 @@
 	read_lock_irqsave(&xtime_lock, flags);
 	{
 		usec = gettimeoffset();
-	
+
 		sec = xtime.tv_sec;
 		usec += xtime.tv_usec;
 	}
@@ -150,10 +142,9 @@
 static void
 timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	int cpu = smp_processor_id();
 	unsigned long new_itm;
 
-	new_itm = itm.next[cpu].count;
+	new_itm = local_cpu_data->itm_next;
 
 	if (!time_after(ia64_get_itc(), new_itm))
 		printk("Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
@@ -165,7 +156,7 @@
 		 * four so that we can use a prof_shift of 2 to get instruction-level
 		 * instead of just bundle-level accuracy.
 		 */
-		if (!user_mode(regs)) 
+		if (!user_mode(regs))
 			do_profile(regs->cr_iip + 4*ia64_psr(regs)->ri);
 
 #ifdef CONFIG_SMP
@@ -183,52 +174,50 @@
 			write_unlock(&xtime_lock);
 		}
 
-		new_itm += itm.delta;
-		itm.next[cpu].count = new_itm;
+		new_itm += local_cpu_data->itm_delta;
+		local_cpu_data->itm_next = new_itm;
 		if (time_after(new_itm, ia64_get_itc()))
 			break;
 	}
 
-	/*
-	 * If we're too close to the next clock tick for comfort, we
-	 * increase the saftey margin by intentionally dropping the
-	 * next tick(s).  We do NOT update itm.next accordingly
-	 * because that would force us to call do_timer() which in
-	 * turn would let our clock run too fast (with the potentially
-	 * devastating effect of losing monotony of time).
-	 */
-	while (!time_after(new_itm, ia64_get_itc() + itm.delta/2))
-		new_itm += itm.delta;
-	ia64_set_itm(new_itm);
-}
-
-#ifdef CONFIG_IA64_SOFTSDV_HACKS
-
-/*
- * Interrupts must be disabled before calling this routine.
- */
-void
-ia64_reset_itm (void)
-{
-	timer_interrupt(0, 0, ia64_task_regs(current));
+	do {
+	    /*
+	     * If we're too close to the next clock tick for comfort, we increase the
+	     * saftey margin by intentionally dropping the next tick(s).  We do NOT update
+	     * itm.next because that would force us to call do_timer() which in turn would
+	     * let our clock run too fast (with the potentially devastating effect of
+	     * losing monotony of time).
+	     */
+	    while (!time_after(new_itm, ia64_get_itc() + local_cpu_data->itm_delta/2))
+	      new_itm += local_cpu_data->itm_delta;
+	    ia64_set_itm(new_itm);
+	    /* double check, in case we got hit by a (slow) PMI: */
+	} while (time_after_eq(ia64_get_itc(), new_itm));
 }
 
-#endif
-
 /*
  * Encapsulate access to the itm structure for SMP.
  */
 void __init
-ia64_cpu_local_tick(void)
+ia64_cpu_local_tick (void)
 {
-#ifdef CONFIG_IA64_SOFTSDV_HACKS
-	ia64_set_itc(0);
-#endif
+	int cpu = smp_processor_id();
+	unsigned long shift = 0, delta;
 
 	/* arrange for the cycle counter to generate a timer interrupt: */
-	ia64_set_itv(TIMER_IRQ, 0);
-	itm.next[smp_processor_id()].count = ia64_get_itc() + itm.delta;
-	ia64_set_itm(itm.next[smp_processor_id()].count);
+	ia64_set_itv(IA64_TIMER_VECTOR);
+
+	delta = local_cpu_data->itm_delta;
+	/*
+	 * Stagger the timer tick for each CPU so they don't occur all at (almost) the
+	 * same time:
+	 */
+	if (cpu) {
+		unsigned long hi = 1UL << ia64_fls(cpu);
+		shift = (2*(cpu - hi) + 1) * delta/hi/2;
+	}
+	local_cpu_data->itm_next = ia64_get_itc() + delta + shift;
+	ia64_set_itm(local_cpu_data->itm_next);
 }
 
 void __init
@@ -258,33 +247,28 @@
 		itc_ratio.num = 3;
 		itc_ratio.den = 1;
 	}
-#ifdef CONFIG_IA64_SOFTSDV_HACKS
-	platform_base_freq = 10000000;
-	proc_ratio.num = 4; proc_ratio.den = 1;
-	itc_ratio.num  = 4; itc_ratio.den  = 1;
-#else
 	if (platform_base_freq < 40000000) {
 		printk("Platform base frequency %lu bogus---resetting to 75MHz!\n",
 		       platform_base_freq);
 		platform_base_freq = 75000000;
 	}
-#endif
 	if (!proc_ratio.den)
-		proc_ratio.num = 1;	/* avoid division by zero */
+		proc_ratio.den = 1;	/* avoid division by zero */
 	if (!itc_ratio.den)
-		itc_ratio.num = 1;	/* avoid division by zero */
+		itc_ratio.den = 1;	/* avoid division by zero */
 
-        itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
-        itm.delta = itc_freq / HZ;
-        printk("CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, ITC freq=%lu.%03luMHz\n",
+	itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
+	local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ;
+	printk("CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, ITC freq=%lu.%03luMHz\n",
 	       smp_processor_id(),
 	       platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
-               itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
+	       itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
 
-	my_cpu_data.proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
-	my_cpu_data.itc_freq = itc_freq;
-	my_cpu_data.cyc_per_usec = itc_freq / 1000000;
-	my_cpu_data.usec_per_cyc = (1000000UL << IA64_USEC_PER_CYC_SHIFT) / itc_freq;
+	local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
+	local_cpu_data->itc_freq = itc_freq;
+	local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000;
+	local_cpu_data->usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT)
+					+ itc_freq/2)/itc_freq;
 
 	/* Setup the CPU local timer tick */
 	ia64_cpu_local_tick();
@@ -299,11 +283,7 @@
 void __init
 time_init (void)
 {
-	/* we can't do request_irq() here because the kmalloc() would fail... */
-	irq_desc[TIMER_IRQ].status |= IRQ_PER_CPU;
-	irq_desc[TIMER_IRQ].handler = &irq_type_ia64_sapic;
-	setup_irq(TIMER_IRQ, &timer_irqaction);
-
+	register_percpu_irq(IA64_TIMER_VECTOR, &timer_irqaction);
 	efi_gettimeofday(&xtime);
 	ia64_init_itm();
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/traps.c linux/arch/ia64/kernel/traps.c
--- v2.4.3/linux/arch/ia64/kernel/traps.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/traps.c	Thu Apr  5 12:51:47 2001
@@ -7,8 +7,6 @@
  * 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE
  */
 
-#define FPSWA_DEBUG	1
-
 /*
  * The fpu_fault() handler needs to be able to access and update all
  * floating point registers.  Those saved in pt_regs can be accessed
@@ -47,31 +45,10 @@
 void __init
 trap_init (void)
 {
-	printk("fpswa interface at %lx\n", ia64_boot_param.fpswa);
-	if (ia64_boot_param.fpswa) {
-#define OLD_FIRMWARE
-#ifdef OLD_FIRMWARE
-		/*
-		 * HACK to work around broken firmware.  This code
-		 * applies the label fixup to the FPSWA interface and
-		 * works both with old and new (fixed) firmware.
-		 */
-		unsigned long addr = (unsigned long) __va(ia64_boot_param.fpswa);
-		unsigned long gp_val = *(unsigned long *)(addr + 8);
-
-		/* go indirect and indexed to get table address */
-		addr = gp_val;
-		gp_val = *(unsigned long *)(addr + 8);
-
-		while (gp_val == *(unsigned long *)(addr + 8)) {
-			*(unsigned long *)addr |= PAGE_OFFSET;
-			*(unsigned long *)(addr + 8) |= PAGE_OFFSET;
-			addr += 16;
-		}
-#endif
+	printk("fpswa interface at %lx\n", ia64_boot_param->fpswa);
+	if (ia64_boot_param->fpswa)
 		/* FPSWA fixup: make the interface pointer a kernel virtual address: */
-		fpswa_interface = __va(ia64_boot_param.fpswa);
-	}
+		fpswa_interface = __va(ia64_boot_param->fpswa);
 }
 
 void
@@ -240,6 +217,7 @@
 {
 	fp_state_t fp_state;
 	fpswa_ret_t ret;
+#define FPSWA_BUG
 #ifdef FPSWA_BUG
 	struct ia64_fpreg f6_15[10];
 #endif
@@ -250,7 +228,7 @@
 	memset(&fp_state, 0, sizeof(fp_state_t));
 
 	/*
-	 * compute fp_state.  only FP registers f6 - f11 are used by the 
+	 * compute fp_state.  only FP registers f6 - f11 are used by the
 	 * kernel, so set those bits in the mask and set the low volatile
 	 * pointer to point to these registers.
 	 */
@@ -263,15 +241,15 @@
 	f6_15[1] = regs->f7;
 	f6_15[2] = regs->f8;
 	f6_15[3] = regs->f9;
- 	__asm__ ("stf.spill %0=f10%P0" : "=m"(f6_15[4]));
- 	__asm__ ("stf.spill %0=f11%P0" : "=m"(f6_15[5]));
- 	__asm__ ("stf.spill %0=f12%P0" : "=m"(f6_15[6]));
- 	__asm__ ("stf.spill %0=f13%P0" : "=m"(f6_15[7]));
- 	__asm__ ("stf.spill %0=f14%P0" : "=m"(f6_15[8]));
- 	__asm__ ("stf.spill %0=f15%P0" : "=m"(f6_15[9]));
+	__asm__ ("stf.spill %0=f10%P0" : "=m"(f6_15[4]));
+	__asm__ ("stf.spill %0=f11%P0" : "=m"(f6_15[5]));
+	__asm__ ("stf.spill %0=f12%P0" : "=m"(f6_15[6]));
+	__asm__ ("stf.spill %0=f13%P0" : "=m"(f6_15[7]));
+	__asm__ ("stf.spill %0=f14%P0" : "=m"(f6_15[8]));
+	__asm__ ("stf.spill %0=f15%P0" : "=m"(f6_15[9]));
 	fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) f6_15;
 #endif
-        /*
+	/*
 	 * unsigned long (*EFI_FPSWA) (
 	 *      unsigned long    trap_type,
 	 *	void             *Bundle,
@@ -287,12 +265,12 @@
 					(unsigned long *) isr, (unsigned long *) pr,
 					(unsigned long *) ifs, &fp_state);
 #ifdef FPSWA_BUG
- 	__asm__ ("ldf.fill f10=%0%P0" :: "m"(f6_15[4]));
- 	__asm__ ("ldf.fill f11=%0%P0" :: "m"(f6_15[5]));
- 	__asm__ ("ldf.fill f12=%0%P0" :: "m"(f6_15[6]));
- 	__asm__ ("ldf.fill f13=%0%P0" :: "m"(f6_15[7]));
- 	__asm__ ("ldf.fill f14=%0%P0" :: "m"(f6_15[8]));
- 	__asm__ ("ldf.fill f15=%0%P0" :: "m"(f6_15[9]));
+	__asm__ ("ldf.fill f10=%0%P0" :: "m"(f6_15[4]));
+	__asm__ ("ldf.fill f11=%0%P0" :: "m"(f6_15[5]));
+	__asm__ ("ldf.fill f12=%0%P0" :: "m"(f6_15[6]));
+	__asm__ ("ldf.fill f13=%0%P0" :: "m"(f6_15[7]));
+	__asm__ ("ldf.fill f14=%0%P0" :: "m"(f6_15[8]));
+	__asm__ ("ldf.fill f15=%0%P0" :: "m"(f6_15[9]));
 	regs->f6 = f6_15[0];
 	regs->f7 = f6_15[1];
 	regs->f8 = f6_15[2];
@@ -319,21 +297,20 @@
 	if (copy_from_user(bundle, (void *) fault_ip, sizeof(bundle)))
 		return -1;
 
-#ifdef FPSWA_DEBUG
-	if (fpu_swa_count > 5 && jiffies - last_time > 5*HZ)
+	if (jiffies - last_time > 5*HZ)
 		fpu_swa_count = 0;
 	if (++fpu_swa_count < 5) {
 		last_time = jiffies;
-		printk("%s(%d): floating-point assist fault at ip %016lx\n",
+		printk(KERN_WARNING "%s(%d): floating-point assist fault at ip %016lx\n",
 		       current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri);
 	}
-#endif
+
 	exception = fp_emulate(fp_fault, bundle, &regs->cr_ipsr, &regs->ar_fpsr, &isr, &regs->pr,
- 			       &regs->cr_ifs, regs);
+			       &regs->cr_ifs, regs);
 	if (fp_fault) {
 		if (exception == 0) {
 			/* emulation was successful */
- 			ia64_increment_ip(regs);
+			ia64_increment_ip(regs);
 		} else if (exception == -1) {
 			printk("handle_fpu_swa: fp_emulate() returned -1\n");
 			return -1;
@@ -392,7 +369,7 @@
 	struct siginfo si;
 	char buf[128];
 
-#ifdef CONFIG_IA64_BRL_EMU	
+#ifdef CONFIG_IA64_BRL_EMU
 	{
 		extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long);
 
@@ -431,7 +408,7 @@
 		"IA-64 Reserved Register/Field fault",
 		"Disabled Instruction Set Transition fault",
 		"Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
-		"Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12", 
+		"Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12",
 		"Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
 	};
 
@@ -444,7 +421,7 @@
 		unsigned long n = vector;
 		char buf[32], *cp;
 
-		if (count > 5 && jiffies - last_time > 5*HZ)
+		if (jiffies - last_time > 5*HZ)
 			count = 0;
 
 		if (count++ < 5) {
@@ -502,7 +479,7 @@
 	      case 35: /* Taken Branch Trap */
 	      case 36: /* Single Step Trap */
 		switch (vector) {
-		      case 29: 
+		      case 29:
 			siginfo.si_code = TRAP_HWBKPT;
 #ifdef CONFIG_ITANIUM
 			/*
@@ -513,7 +490,7 @@
 			  ifa = regs->cr_iip;
 #endif
 			siginfo.si_addr = (void *) ifa;
-		        break;
+			break;
 		      case 35: siginfo.si_code = TRAP_BRANCH; break;
 		      case 36: siginfo.si_code = TRAP_TRACE; break;
 		}
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/unaligned.c linux/arch/ia64/kernel/unaligned.c
--- v2.4.3/linux/arch/ia64/kernel/unaligned.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/unaligned.c	Thu Apr  5 12:51:47 2001
@@ -1,12 +1,16 @@
 /*
  * Architecture-specific unaligned trap handling.
  *
- * Copyright (C) 1999-2000 Hewlett-Packard Co
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
  * Copyright (C) 1999-2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * 2001/01/17	Add support emulation of unaligned kernel accesses.
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
+
 #include <asm/uaccess.h>
 #include <asm/rse.h>
 #include <asm/processor.h>
@@ -17,14 +21,28 @@
 #undef DEBUG_UNALIGNED_TRAP
 
 #ifdef DEBUG_UNALIGNED_TRAP
-#define DPRINT(a) { printk("%s, line %d: ", __FUNCTION__, __LINE__); printk a;}
+# define DPRINT(a...)	do { printk("%s.%u: ", __FUNCTION__, __LINE__); printk (a); } while (0)
+# define DDUMP(str,vp,len)	dump(str, vp, len)
+
+static void
+dump (const char *str, void *vp, size_t len)
+{
+	unsigned char *cp = vp;
+	int i;
+
+	printk("%s", str);
+	for (i = 0; i < len; ++i)
+		printk (" %02x", *cp++);
+	printk("\n");
+}
 #else
-#define DPRINT(a)
+# define DPRINT(a...)
+# define DDUMP(str,vp,len)
 #endif
 
 #define IA64_FIRST_STACKED_GR	32
 #define IA64_FIRST_ROTATING_FR	32
-#define SIGN_EXT9		__IA64_UL(0xffffffffffffff00)
+#define SIGN_EXT9		0xffffffffffffff00ul
 
 /*
  * For M-unit:
@@ -35,33 +53,34 @@
  * --------|------|---------|
  *     4   |   1  |    6    | = 11 bits
  * --------------------------
- * However bits [31:30] are not directly useful to distinguish between 
- * load/store so we can use [35:32] instead, which gives the following 
+ * However bits [31:30] are not directly useful to distinguish between
+ * load/store so we can use [35:32] instead, which gives the following
  * mask ([40:32]) using 9 bits. The 'e' comes from the fact that we defer
  * checking the m-bit until later in the load/store emulation.
  */
-#define IA64_OPCODE_MASK	0x1ef00000000
+#define IA64_OPCODE_MASK	0x1ef
+#define IA64_OPCODE_SHIFT	32
 
 /*
  * Table C-28 Integer Load/Store
- * 
+ *
  * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF
  *
- * ld8.fill, st8.fill  MUST be aligned because the RNATs are based on 
+ * ld8.fill, st8.fill  MUST be aligned because the RNATs are based on
  * the address (bits [8:3]), so we must failed.
  */
-#define LD_OP            0x08000000000
-#define LDS_OP           0x08100000000
-#define LDA_OP           0x08200000000
-#define LDSA_OP          0x08300000000
-#define LDBIAS_OP        0x08400000000
-#define LDACQ_OP         0x08500000000
+#define LD_OP            0x080
+#define LDS_OP           0x081
+#define LDA_OP           0x082
+#define LDSA_OP          0x083
+#define LDBIAS_OP        0x084
+#define LDACQ_OP         0x085
 /* 0x086, 0x087 are not relevant */
-#define LDCCLR_OP        0x08800000000
-#define LDCNC_OP         0x08900000000
-#define LDCCLRACQ_OP     0x08a00000000
-#define ST_OP            0x08c00000000
-#define STREL_OP         0x08d00000000
+#define LDCCLR_OP        0x088
+#define LDCNC_OP         0x089
+#define LDCCLRACQ_OP     0x08a
+#define ST_OP            0x08c
+#define STREL_OP         0x08d
 /* 0x08e,0x8f are not relevant */
 
 /*
@@ -73,38 +92,38 @@
 
 /*
  * Table C-30 Integer Load/Store +Imm
- * 
+ *
  * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF
  *
- * ld8.fill, st8.fill  must be aligned because the Nat register are based on 
+ * ld8.fill, st8.fill  must be aligned because the Nat register are based on
  * the address, so we must fail and the program must be fixed.
  */
-#define LD_IMM_OP            0x0a000000000
-#define LDS_IMM_OP           0x0a100000000
-#define LDA_IMM_OP           0x0a200000000
-#define LDSA_IMM_OP          0x0a300000000
-#define LDBIAS_IMM_OP        0x0a400000000
-#define LDACQ_IMM_OP         0x0a500000000
+#define LD_IMM_OP            0x0a0
+#define LDS_IMM_OP           0x0a1
+#define LDA_IMM_OP           0x0a2
+#define LDSA_IMM_OP          0x0a3
+#define LDBIAS_IMM_OP        0x0a4
+#define LDACQ_IMM_OP         0x0a5
 /* 0x0a6, 0xa7 are not relevant */
-#define LDCCLR_IMM_OP        0x0a800000000
-#define LDCNC_IMM_OP         0x0a900000000
-#define LDCCLRACQ_IMM_OP     0x0aa00000000
-#define ST_IMM_OP            0x0ac00000000
-#define STREL_IMM_OP         0x0ad00000000
+#define LDCCLR_IMM_OP        0x0a8
+#define LDCNC_IMM_OP         0x0a9
+#define LDCCLRACQ_IMM_OP     0x0aa
+#define ST_IMM_OP            0x0ac
+#define STREL_IMM_OP         0x0ad
 /* 0x0ae,0xaf are not relevant */
 
 /*
  * Table C-32 Floating-point Load/Store
  */
-#define LDF_OP           0x0c000000000
-#define LDFS_OP          0x0c100000000
-#define LDFA_OP          0x0c200000000
-#define LDFSA_OP         0x0c300000000
+#define LDF_OP           0x0c0
+#define LDFS_OP          0x0c1
+#define LDFA_OP          0x0c2
+#define LDFSA_OP         0x0c3
 /* 0x0c6 is irrelevant */
-#define LDFCCLR_OP       0x0c800000000
-#define LDFCNC_OP        0x0c900000000
+#define LDFCCLR_OP       0x0c8
+#define LDFCNC_OP        0x0c9
 /* 0x0cb is irrelevant  */
-#define STF_OP           0x0cc00000000
+#define STF_OP           0x0cc
 
 /*
  * Table C-33 Floating-point Load +Reg
@@ -116,17 +135,17 @@
 /*
  * Table C-34 Floating-point Load/Store +Imm
  */
-#define LDF_IMM_OP       0x0e000000000
-#define LDFS_IMM_OP      0x0e100000000
-#define LDFA_IMM_OP      0x0e200000000
-#define LDFSA_IMM_OP     0x0e300000000
+#define LDF_IMM_OP       0x0e0
+#define LDFS_IMM_OP      0x0e1
+#define LDFA_IMM_OP      0x0e2
+#define LDFSA_IMM_OP     0x0e3
 /* 0x0e6 is irrelevant */
-#define LDFCCLR_IMM_OP   0x0e800000000
-#define LDFCNC_IMM_OP    0x0e900000000
-#define STF_IMM_OP       0x0ec00000000
+#define LDFCCLR_IMM_OP   0x0e8
+#define LDFCNC_IMM_OP    0x0e9
+#define STF_IMM_OP       0x0ec
 
 typedef struct {
-	unsigned long  	 qp:6;	/* [0:5]   */
+	unsigned long	 qp:6;	/* [0:5]   */
 	unsigned long    r1:7;	/* [6:12]  */
 	unsigned long   imm:7;	/* [13:19] */
 	unsigned long    r3:7;	/* [20:26] */
@@ -170,7 +189,7 @@
 #define FR_IN_SW(x)	(fr_info[x] & 0x1)
 
 static u16 gr_info[32]={
-	0, 			/* r0 is read-only : WE SHOULD NEVER GET THIS */
+	0,			/* r0 is read-only : WE SHOULD NEVER GET THIS */
 
 	RPT(r1), RPT(r2), RPT(r3),
 
@@ -186,7 +205,7 @@
 };
 
 static u16 fr_info[32]={
-	0, 			/* constant : WE SHOULD NEVER GET THIS */
+	0,			/* constant : WE SHOULD NEVER GET THIS */
 	0,			/* constant : WE SHOULD NEVER GET THIS */
 
 	RSW(f2), RSW(f3), RSW(f4), RSW(f5),
@@ -255,162 +274,160 @@
 }
 
 static void
-set_rse_reg(struct pt_regs *regs, unsigned long r1, unsigned long val, int nat)
+set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, int nat)
 {
-	struct switch_stack *sw = (struct switch_stack *)regs - 1;
-	unsigned long *kbs	= ((unsigned long *)current) + IA64_RBS_OFFSET/8;
+	struct switch_stack *sw = (struct switch_stack *) regs - 1;
+	unsigned long *bsp, *bspstore, *addr, *rnat_addr, *ubs_end;
+	unsigned long *kbs = (void *) current + IA64_RBS_OFFSET;
+	unsigned long rnats, nat_mask;
 	unsigned long on_kbs;
-	unsigned long *bsp, *bspstore, *addr, *ubs_end, *slot;
-	unsigned long rnats;
-	long nlocals;
+	long sof = (regs->cr_ifs) & 0x7f;
 
-	/*
-	 * cr_ifs=[rv:ifm], ifm=[....:sof(6)]
-	 * nlocal=number of locals (in+loc) register of the faulting function
-	 */
-	nlocals = (regs->cr_ifs) & 0x7f;
+	DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld\n",
+	       r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f);
 
-	DPRINT(("sw.bsptore=%lx pt.bspstore=%lx\n", sw->ar_bspstore, regs->ar_bspstore));
-	DPRINT(("cr.ifs=%lx sof=%ld sol=%ld\n",
-		regs->cr_ifs, regs->cr_ifs &0x7f, (regs->cr_ifs>>7)&0x7f));
+	if ((r1 - 32) >= sof) {
+		/* this should never happen, as the "rsvd register fault" has higher priority */
+		DPRINT("ignoring write to r%lu; only %lu registers are allocated!\n", r1, sof);
+		return;
+	}
 
-	on_kbs   = ia64_rse_num_regs(kbs, (unsigned long *)sw->ar_bspstore);
-	bspstore = (unsigned long *)regs->ar_bspstore;
+	on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
+	addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + (r1 - 32));
+	if (addr >= kbs) {
+		/* the register is on the kernel backing store: easy... */
+		rnat_addr = ia64_rse_rnat_addr(addr);
+		if ((unsigned long) rnat_addr >= sw->ar_bspstore)
+			rnat_addr = &sw->ar_rnat;
+		nat_mask = 1UL << ia64_rse_slot_num(addr);
 
-	DPRINT(("rse_slot_num=0x%lx\n",ia64_rse_slot_num((unsigned long *)sw->ar_bspstore)));
-	DPRINT(("kbs=%p nlocals=%ld\n", (void *) kbs, nlocals));
-	DPRINT(("bspstore next rnat slot %p\n",
-		(void *) ia64_rse_rnat_addr((unsigned long *)sw->ar_bspstore)));
-	DPRINT(("on_kbs=%ld rnats=%ld\n",
-		on_kbs, ((sw->ar_bspstore-(unsigned long)kbs)>>3) - on_kbs));
+		*addr = val;
+		if (nat)
+			*rnat_addr |=  nat_mask;
+		else
+			*rnat_addr &= ~nat_mask;
+		return;
+	}
 
 	/*
-	 * See get_rse_reg() for an explanation on the following instructions
+	 * Avoid using user_mode() here: with "epc", we cannot use the privilege level to
+	 * infer whether the interrupt task was running on the kernel backing store.
 	 */
+	if (regs->r12 >= TASK_SIZE) {
+		DPRINT("ignoring kernel write to r%lu; register isn't on the RBS!", r1);
+		return;
+	}
+
+	bspstore = (unsigned long *) regs->ar_bspstore;
 	ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
-	bsp     = ia64_rse_skip_regs(ubs_end, -nlocals);
-	addr    = slot = ia64_rse_skip_regs(bsp, r1 - 32);
+	bsp     = ia64_rse_skip_regs(ubs_end, -sof);
+	addr    = ia64_rse_skip_regs(bsp, r1 - 32);
 
-	DPRINT(("ubs_end=%p bsp=%p addr=%p slot=0x%lx\n",
-		(void *) ubs_end, (void *) bsp, (void *) addr, ia64_rse_slot_num(addr)));
+	DPRINT("ubs_end=%p bsp=%p addr=%px\n", (void *) ubs_end, (void *) bsp, (void *) addr);
 
-	ia64_poke(regs, current, (unsigned long)addr, val);
+	ia64_poke(current, (unsigned long) ubs_end, (unsigned long) addr, val);
 
-	/*
-	 * addr will now contain the address of the RNAT for the register
-	 */
-	addr = ia64_rse_rnat_addr(addr);
+	rnat_addr = ia64_rse_rnat_addr(addr);
 
-	ia64_peek(regs, current, (unsigned long)addr, &rnats);
-	DPRINT(("rnat @%p = 0x%lx nat=%d rnatval=%lx\n",
-		(void *) addr, rnats, nat, rnats &ia64_rse_slot_num(slot)));
-	
-	if (nat) {
-		rnats |= __IA64_UL(1) << ia64_rse_slot_num(slot);
-	} else {
-		rnats &= ~(__IA64_UL(1) << ia64_rse_slot_num(slot));
-	}
-	ia64_poke(regs, current, (unsigned long)addr, rnats);
+	ia64_peek(current, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats);
+	DPRINT("rnat @%p = 0x%lx nat=%d old nat=%ld\n",
+	       (void *) rnat_addr, rnats, nat, (rnats >> ia64_rse_slot_num(addr)) & 1);
 
-	DPRINT(("rnat changed to @%p = 0x%lx\n", (void *) addr, rnats));
+	nat_mask = 1UL << ia64_rse_slot_num(addr);
+	if (nat)
+		rnats |=  nat_mask;
+	else
+		rnats &= ~nat_mask;
+	ia64_poke(current, (unsigned long) ubs_end, (unsigned long) rnat_addr, rnats);
+
+	DPRINT("rnat changed to @%p = 0x%lx\n", (void *) rnat_addr, rnats);
 }
 
 
 static void
-get_rse_reg(struct pt_regs *regs, unsigned long r1, unsigned long *val, int *nat)
+get_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long *val, int *nat)
 {
-	struct switch_stack *sw = (struct switch_stack *)regs - 1;
-	unsigned long *kbs	= (unsigned long *)current + IA64_RBS_OFFSET/8;
+	struct switch_stack *sw = (struct switch_stack *) regs - 1;
+	unsigned long *bsp, *addr, *rnat_addr, *ubs_end, *bspstore;
+	unsigned long *kbs = (void *) current + IA64_RBS_OFFSET;
+	unsigned long rnats, nat_mask;
 	unsigned long on_kbs;
-	long nlocals;
-	unsigned long *bsp, *addr, *ubs_end, *slot, *bspstore;
-	unsigned long rnats;
+	long sof = (regs->cr_ifs) & 0x7f;
 
-	/*
-	 * cr_ifs=[rv:ifm], ifm=[....:sof(6)]
-	 * nlocals=number of local registers in the faulting function
-	 */
-	nlocals = (regs->cr_ifs) & 0x7f;
+	DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld\n",
+	       r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f);
 
-	/*
-	 * save_switch_stack does a flushrs and saves bspstore.
-	 * on_kbs = actual number of registers saved on kernel backing store
-	 *          (taking into accound potential RNATs)
-	 *
-	 * Note that this number can be greater than nlocals if the dirty
-	 * parititions included more than one stack frame at the time we
-	 * switched to KBS
-	 */
-	on_kbs   = ia64_rse_num_regs(kbs, (unsigned long *)sw->ar_bspstore);
-	bspstore = (unsigned long *)regs->ar_bspstore;
+	if ((r1 - 32) >= sof) {
+		/* this should never happen, as the "rsvd register fault" has higher priority */
+		DPRINT("ignoring read from r%lu; only %lu registers are allocated!\n", r1, sof);
+		return;
+	}
+
+	on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
+	addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + (r1 - 32));
+	if (addr >= kbs) {
+		/* the register is on the kernel backing store: easy... */
+		*val = *addr;
+		if (nat) {
+			rnat_addr = ia64_rse_rnat_addr(addr);
+			if ((unsigned long) rnat_addr >= sw->ar_bspstore)
+				rnat_addr = &sw->ar_rnat;
+			nat_mask = 1UL << ia64_rse_slot_num(addr);
+			*nat = (*rnat_addr & nat_mask) != 0;
+		}
+		return;
+	}
 
 	/*
-	 * To simplify the logic, we calculate everything as if there was only
-	 * one backing store i.e., the user one (UBS). We let it to peek/poke
-	 * to figure out whether the register we're looking for really is
-	 * on the UBS or on KBS.
-	 *
-	 * regs->ar_bsptore = address of last register saved on UBS (before switch)
-	 *
-	 * ubs_end = virtual end of the UBS (if everything had been spilled there)
-	 *
-	 * We know that ubs_end is the point where the last register on the
-	 * stack frame we're interested in as been saved. So we need to walk
-	 * our way backward to figure out what the BSP "was" for that frame,
-	 * this will give us the location of r32. 
-	 *
-	 * bsp = "virtual UBS" address of r32 for our frame
-	 *
-	 * Finally, get compute the address of the register we're looking for
-	 * using bsp as our base (move up again).
-	 *
-	 * Please note that in our case, we know that the register is necessarily
-	 * on the KBS because we are only interested in the current frame at the moment
-	 * we got the exception i.e., bsp is not changed until we switch to KBS.
+	 * Avoid using user_mode() here: with "epc", we cannot use the privilege level to
+	 * infer whether the interrupt task was running on the kernel backing store.
 	 */
+	if (regs->r12 >= TASK_SIZE) {
+		DPRINT("ignoring kernel read of r%lu; register isn't on the RBS!", r1);
+		return;
+	}
+
+	bspstore = (unsigned long *)regs->ar_bspstore;
 	ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
-	bsp     = ia64_rse_skip_regs(ubs_end, -nlocals);
-	addr    = slot = ia64_rse_skip_regs(bsp, r1 - 32);
+	bsp     = ia64_rse_skip_regs(ubs_end, -sof);
+	addr    = ia64_rse_skip_regs(bsp, r1 - 32);
 
-	DPRINT(("ubs_end=%p bsp=%p addr=%p slot=0x%lx\n",
-		(void *) ubs_end, (void *) bsp, (void *) addr, ia64_rse_slot_num(addr)));
-	
-	ia64_peek(regs, current, (unsigned long)addr, val);
+	DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
 
-	/*
-	 * addr will now contain the address of the RNAT for the register
-	 */
-	addr = ia64_rse_rnat_addr(addr);
+	ia64_peek(current, (unsigned long) ubs_end, (unsigned long) addr, val);
 
-	ia64_peek(regs, current, (unsigned long)addr, &rnats);
-	DPRINT(("rnat @%p = 0x%lx\n", (void *) addr, rnats));
-	
-	if (nat)
-		*nat = rnats >> ia64_rse_slot_num(slot) & 0x1;
+	if (nat) {
+		rnat_addr = ia64_rse_rnat_addr(addr);
+		nat_mask = 1UL << ia64_rse_slot_num(addr);
+
+		DPRINT("rnat @%p = 0x%lx\n", (void *) rnat_addr, rnats);
+
+		ia64_peek(current, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats);
+		*nat = (rnats & nat_mask) != 0;
+	}
 }
 
 
 static void
-setreg(unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs)
+setreg (unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs)
 {
-	struct switch_stack *sw = (struct switch_stack *)regs -1;
+	struct switch_stack *sw = (struct switch_stack *) regs - 1;
 	unsigned long addr;
 	unsigned long bitmask;
 	unsigned long *unat;
 
-
 	/*
 	 * First takes care of stacked registers
 	 */
- 	if (regnum >= IA64_FIRST_STACKED_GR) {
+	if (regnum >= IA64_FIRST_STACKED_GR) {
 		set_rse_reg(regs, regnum, val, nat);
 		return;
 	}
 
 	/*
-	 * Using r0 as a target raises a General Exception fault which has 
-	 * higher priority than the Unaligned Reference fault.
-	 */ 
+	 * Using r0 as a target raises a General Exception fault which has higher priority
+	 * than the Unaligned Reference fault.
+	 */
 
 	/*
 	 * Now look at registers in [0-31] range and init correct UNAT
@@ -422,8 +439,8 @@
 		addr = (unsigned long)regs;
 		unat = &sw->caller_unat;
 	}
-	DPRINT(("tmp_base=%lx switch_stack=%s offset=%d\n",
-		addr, unat==&sw->ar_unat ? "yes":"no", GR_OFFS(regnum)));
+	DPRINT("tmp_base=%lx switch_stack=%s offset=%d\n",
+	       addr, unat==&sw->ar_unat ? "yes":"no", GR_OFFS(regnum));
 	/*
 	 * add offset from base of struct
 	 * and do it !
@@ -436,20 +453,20 @@
 	 * We need to clear the corresponding UNAT bit to fully emulate the load
 	 * UNAT bit_pos = GR[r3]{8:3} form EAS-2.4
 	 */
-	bitmask   = __IA64_UL(1) << (addr >> 3 & 0x3f);
-	DPRINT(("*0x%lx=0x%lx NaT=%d prev_unat @%p=%lx\n", addr, val, nat, (void *) unat, *unat));
+	bitmask   = 1UL << (addr >> 3 & 0x3f);
+	DPRINT("*0x%lx=0x%lx NaT=%d prev_unat @%p=%lx\n", addr, val, nat, (void *) unat, *unat);
 	if (nat) {
 		*unat |= bitmask;
 	} else {
 		*unat &= ~bitmask;
 	}
-	DPRINT(("*0x%lx=0x%lx NaT=%d new unat: %p=%lx\n", addr, val, nat, (void *) unat,*unat));
+	DPRINT("*0x%lx=0x%lx NaT=%d new unat: %p=%lx\n", addr, val, nat, (void *) unat,*unat);
 }
 
 #define IA64_FPH_OFFS(r) (r - IA64_FIRST_ROTATING_FR)
 
 static void
-setfpreg(unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs)
+setfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs)
 {
 	struct switch_stack *sw = (struct switch_stack *)regs - 1;
 	unsigned long addr;
@@ -465,7 +482,7 @@
 	 *
 	 * For now, we are using approach (1).
 	 */
- 	if (regnum >= IA64_FIRST_ROTATING_FR) {
+	if (regnum >= IA64_FIRST_ROTATING_FR) {
 		ia64_sync_fph(current);
 		current->thread.fph[IA64_FPH_OFFS(regnum)] = *fpval;
 	} else {
@@ -477,18 +494,18 @@
 		} else {
 			addr = (unsigned long)regs;
 		}
-		
-		DPRINT(("tmp_base=%lx offset=%d\n", addr, FR_OFFS(regnum)));
+
+		DPRINT("tmp_base=%lx offset=%d\n", addr, FR_OFFS(regnum));
 
 		addr += FR_OFFS(regnum);
 		*(struct ia64_fpreg *)addr = *fpval;
 
 		/*
-	 	 * mark the low partition as being used now
+		 * mark the low partition as being used now
 		 *
 		 * It is highly unlikely that this bit is not already set, but
 		 * let's do it for safety.
-	 	 */
+		 */
 		regs->cr_ipsr |= IA64_PSR_MFL;
 	}
 }
@@ -497,40 +514,40 @@
  * Those 2 inline functions generate the spilled versions of the constant floating point
  * registers which can be used with stfX
  */
-static inline void 
-float_spill_f0(struct ia64_fpreg *final)
+static inline void
+float_spill_f0 (struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("stf.spill [%0]=f0" :: "r"(final) : "memory");
 }
 
-static inline void 
-float_spill_f1(struct ia64_fpreg *final)
+static inline void
+float_spill_f1 (struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("stf.spill [%0]=f1" :: "r"(final) : "memory");
 }
 
 static void
-getfpreg(unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs)
+getfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs)
 {
-	struct switch_stack *sw = (struct switch_stack *)regs -1;
+	struct switch_stack *sw = (struct switch_stack *) regs - 1;
 	unsigned long addr;
 
 	/*
-	 * From EAS-2.5: FPDisableFault has higher priority than 
-	 * Unaligned Fault. Thus, when we get here, we know the partition is 
+	 * From EAS-2.5: FPDisableFault has higher priority than
+	 * Unaligned Fault. Thus, when we get here, we know the partition is
 	 * enabled.
 	 *
 	 * When regnum > 31, the register is still live and we need to force a save
 	 * to current->thread.fph to get access to it.  See discussion in setfpreg()
 	 * for reasons and other ways of doing this.
 	 */
- 	if (regnum >= IA64_FIRST_ROTATING_FR) {
+	if (regnum >= IA64_FIRST_ROTATING_FR) {
 		ia64_flush_fph(current);
 		*fpval = current->thread.fph[IA64_FPH_OFFS(regnum)];
 	} else {
 		/*
 		 * f0 = 0.0, f1= 1.0. Those registers are constant and are thus
-	 	 * not saved, we must generate their spilled form on the fly
+		 * not saved, we must generate their spilled form on the fly
 		 */
 		switch(regnum) {
 		case 0:
@@ -546,8 +563,8 @@
 			addr =  FR_IN_SW(regnum) ? (unsigned long)sw
 						 : (unsigned long)regs;
 
-			DPRINT(("is_sw=%d tmp_base=%lx offset=0x%x\n",
-				FR_IN_SW(regnum), addr, FR_OFFS(regnum)));
+			DPRINT("is_sw=%d tmp_base=%lx offset=0x%x\n",
+			       FR_IN_SW(regnum), addr, FR_OFFS(regnum));
 
 			addr  += FR_OFFS(regnum);
 			*fpval = *(struct ia64_fpreg *)addr;
@@ -557,12 +574,12 @@
 
 
 static void
-getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs)
+getreg (unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs)
 {
-	struct switch_stack *sw = (struct switch_stack *)regs -1;
+	struct switch_stack *sw = (struct switch_stack *) regs - 1;
 	unsigned long addr, *unat;
 
- 	if (regnum >= IA64_FIRST_STACKED_GR) {
+	if (regnum >= IA64_FIRST_STACKED_GR) {
 		get_rse_reg(regs, regnum, val, nat);
 		return;
 	}
@@ -588,7 +605,7 @@
 		unat = &sw->caller_unat;
 	}
 
-	DPRINT(("addr_base=%lx offset=0x%x\n", addr,  GR_OFFS(regnum)));
+	DPRINT("addr_base=%lx offset=0x%x\n", addr,  GR_OFFS(regnum));
 
 	addr += GR_OFFS(regnum);
 
@@ -602,16 +619,16 @@
 }
 
 static void
-emulate_load_updates(update_t type, load_store_t *ld, struct pt_regs *regs, unsigned long ifa)
-{		
+emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsigned long ifa)
+{
 	/*
-	 * IMPORTANT: 
+	 * IMPORTANT:
 	 * Given the way we handle unaligned speculative loads, we should
 	 * not get to this point in the code but we keep this sanity check,
 	 * just in case.
 	 */
-	if (ld->x6_op == 1 || ld->x6_op == 3) {
-		printk(KERN_ERR __FUNCTION__": register update on speculative load, error\n");	
+	if (ld.x6_op == 1 || ld.x6_op == 3) {
+		printk(KERN_ERR __FUNCTION__": register update on speculative load, error\n");
 		die_if_kernel("unaligned reference on specualtive load with register update\n",
 			      regs, 30);
 	}
@@ -624,18 +641,18 @@
 	if (type == UPD_IMMEDIATE) {
 		unsigned long imm;
 
-		/* 
-	 	 * Load +Imm: ldXZ r1=[r3],imm(9)
-	 	 *
+		/*
+		 * Load +Imm: ldXZ r1=[r3],imm(9)
+		 *
 		 *
-	   	 * form imm9: [13:19] contain the first 7 bits
-      		 */		 
-		imm = ld->x << 7 | ld->imm;
+		 * form imm9: [13:19] contain the first 7 bits
+		 */
+		imm = ld.x << 7 | ld.imm;
 
 		/*
 		 * sign extend (1+8bits) if m set
 		 */
-		if (ld->m) imm |= SIGN_EXT9;
+		if (ld.m) imm |= SIGN_EXT9;
 
 		/*
 		 * ifa == r3 and we know that the NaT bit on r3 was clear so
@@ -643,109 +660,79 @@
 		 */
 		ifa += imm;
 
-		setreg(ld->r3, ifa, 0, regs);
+		setreg(ld.r3, ifa, 0, regs);
 
-		DPRINT(("ld.x=%d ld.m=%d imm=%ld r3=0x%lx\n", ld->x, ld->m, imm, ifa));
+		DPRINT("ld.x=%d ld.m=%d imm=%ld r3=0x%lx\n", ld.x, ld.m, imm, ifa);
 
-	} else if (ld->m) {
+	} else if (ld.m) {
 		unsigned long r2;
 		int nat_r2;
 
 		/*
 		 * Load +Reg Opcode: ldXZ r1=[r3],r2
 		 *
-		 * Note: that we update r3 even in the case of ldfX.a 
+		 * Note: that we update r3 even in the case of ldfX.a
 		 * (where the load does not happen)
 		 *
 		 * The way the load algorithm works, we know that r3 does not
 		 * have its NaT bit set (would have gotten NaT consumption
-		 * before getting the unaligned fault). So we can use ifa 
+		 * before getting the unaligned fault). So we can use ifa
 		 * which equals r3 at this point.
 		 *
 		 * IMPORTANT:
-	 	 * The above statement holds ONLY because we know that we
+		 * The above statement holds ONLY because we know that we
 		 * never reach this code when trying to do a ldX.s.
-		 * If we ever make it to here on an ldfX.s then 
+		 * If we ever make it to here on an ldfX.s then
 		 */
-		getreg(ld->imm, &r2, &nat_r2, regs);
-		
+		getreg(ld.imm, &r2, &nat_r2, regs);
+
 		ifa += r2;
-		
+
 		/*
 		 * propagate Nat r2 -> r3
 		 */
-		setreg(ld->r3, ifa, nat_r2, regs);
+		setreg(ld.r3, ifa, nat_r2, regs);
 
-		DPRINT(("imm=%d r2=%ld r3=0x%lx nat_r2=%d\n",ld->imm, r2, ifa, nat_r2));
+		DPRINT("imm=%d r2=%ld r3=0x%lx nat_r2=%d\n",ld.imm, r2, ifa, nat_r2);
 	}
 }
 
 
 static int
-emulate_load_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 {
-	unsigned long val;
-	unsigned int len = 1<< ld->x6_sz;
-
-	/*
-	 * the macro supposes sequential access (which is the case)
-	 * if the first byte is an invalid address we return here. Otherwise
-	 * there is a guard page at the top of the user's address page and 
-	 * the first access would generate a NaT consumption fault and return
-	 * with a SIGSEGV, which is what we want.
-	 *
-	 * Note: the first argument is ignored 
-	 */
-	if (access_ok(VERIFY_READ, (void *)ifa, len) < 0) {
-		DPRINT(("verify area failed on %lx\n", ifa));
-		return -1;
-	}
+	unsigned int len = 1 << ld.x6_sz;
 
 	/*
 	 * r0, as target, doesn't need to be checked because Illegal Instruction
 	 * faults have higher priority than unaligned faults.
 	 *
-	 * r0 cannot be found as the base as it would never generate an 
+	 * r0 cannot be found as the base as it would never generate an
 	 * unaligned reference.
 	 */
 
 	/*
-	 * ldX.a we don't try to emulate anything but we must
-	 * invalidate the ALAT entry.
+	 * ldX.a we don't try to emulate anything but we must invalidate the ALAT entry.
 	 * See comment below for explanation on how we handle ldX.a
 	 */
-	if (ld->x6_op != 0x2) {
-		/*
-		 * we rely on the macros in unaligned.h for now i.e.,
-		 * we let the compiler figure out how to read memory gracefully.
-		 *
-		 * We need this switch/case because the way the inline function
-		 * works. The code is optimized by the compiler and looks like
-		 * a single switch/case.
-		 */
-		switch(len) {
-			case 2:
-				val = ia64_get_unaligned((void *)ifa, 2);
-				break;
-			case 4:
-				val = ia64_get_unaligned((void *)ifa, 4);
-				break;
-			case 8:
-				val = ia64_get_unaligned((void *)ifa, 8);
-				break;
-			default:
-				DPRINT(("unknown size: x6=%d\n", ld->x6_sz));
-				return -1;
-		}
+	if (ld.x6_op != 0x2) {
+		unsigned long val = 0;
 
-		setreg(ld->r1, val, 0, regs);
+		if (len != 2 && len != 4 && len != 8) {
+			DPRINT("unknown size: x6=%d\n", ld.x6_sz);
+			return -1;
+		}
+		/* this assumes little-endian byte-order: */
+		if (copy_from_user(&val, (void *) ifa, len))
+		    return -1;
+		setreg(ld.r1, val, 0, regs);
 	}
 
 	/*
 	 * check for updates on any kind of loads
 	 */
-	if (ld->op == 0x5 || ld->m)
-		emulate_load_updates(ld->op == 0x5 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa);
+	if (ld.op == 0x5 || ld.m)
+		emulate_load_updates(ld.op == 0x5 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa);
 
 	/*
 	 * handling of various loads (based on EAS2.4):
@@ -753,7 +740,6 @@
 	 * ldX.acq (ordered load):
 	 *	- acquire semantics would have been used, so force fence instead.
 	 *
-	 *
 	 * ldX.c.clr (check load and clear):
 	 *	- if we get to this handler, it's because the entry was not in the ALAT.
 	 *	  Therefore the operation reverts to a normal load
@@ -764,15 +750,15 @@
 	 * ldX.c.clr.acq (ordered check load and clear):
 	 *	- same as above for c.clr part. The load needs to have acquire semantics. So
 	 *	  we use the fence semantics which is stronger and thus ensures correctness.
-	 *	
+	 *
 	 * ldX.a (advanced load):
-	 *	- suppose ldX.a r1=[r3]. If we get to the unaligned trap it's because the 
-	 * 	  address doesn't match requested size alignement. This means that we would 
+	 *	- suppose ldX.a r1=[r3]. If we get to the unaligned trap it's because the
+	 *	  address doesn't match requested size alignement. This means that we would
 	 *	  possibly need more than one load to get the result.
 	 *
 	 *	  The load part can be handled just like a normal load, however the difficult
 	 *	  part is to get the right thing into the ALAT. The critical piece of information
-	 * 	  in the base address of the load & size. To do that, a ld.a must be executed,
+	 *	  in the base address of the load & size. To do that, a ld.a must be executed,
 	 *	  clearly any address can be pushed into the table by using ld1.a r1=[r3]. Now
 	 *	  if we use the same target register, we will be okay for the check.a instruction.
 	 *	  If we look at the store, basically a stX [r3]=r1 checks the ALAT  for any entry
@@ -791,7 +777,7 @@
 	 *		store & shift to temporary;
 	 *		ld1.a r1=[r3]
 	 *		store & shift to temporary;
-	 * 		r1=temporary
+	 *		r1=temporary
 	 *
 	 *	  So int this case, you would get the right value is r1 but the wrong info in
 	 *	  the ALAT.  Notice that you could do it in reverse to finish with address 3
@@ -815,7 +801,7 @@
 	 *	  So it's okay NOT to do any actual load on an unaligned ld.a. However the ALAT
 	 *	  must be invalidated for the register (so that's chck.a.*,ld.c.* don't pick up
 	 *	  a stale entry later) The register base update MUST also be performed.
-	 *	  
+	 *
 	 *	  Now what is the content of the register and its NaT bit in the case we don't
 	 *	  do the load ?  EAS2.4, says (in case an actual load is needed)
 	 *
@@ -828,40 +814,26 @@
 	 */
 
 	/*
-	 * when the load has the .acq completer then 
+	 * when the load has the .acq completer then
 	 * use ordering fence.
 	 */
-	if (ld->x6_op == 0x5 || ld->x6_op == 0xa)
+	if (ld.x6_op == 0x5 || ld.x6_op == 0xa)
 		mb();
 
 	/*
 	 * invalidate ALAT entry in case of advanced load
 	 */
-	if (ld->x6_op == 0x2)
-		invala_gr(ld->r1);
+	if (ld.x6_op == 0x2)
+		invala_gr(ld.r1);
 
 	return 0;
 }
 
 static int
-emulate_store_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 {
 	unsigned long r2;
-	unsigned int len = 1<< ld->x6_sz;
-	
-	/*
-	 * the macro supposes sequential access (which is the case)
-	 * if the first byte is an invalid address we return here. Otherwise
-	 * there is a guard page at the top of the user's address page and 
-	 * the first access would generate a NaT consumption fault and return
-	 * with a SIGSEGV, which is what we want.
-	 *
-	 * Note: the first argument is ignored 
-	 */
-	if (access_ok(VERIFY_WRITE, (void *)ifa, len) < 0) {
-		DPRINT(("verify area failed on %lx\n",ifa));
-		return -1;
-	}
+	unsigned int len = 1 << ld.x6_sz;
 
 	/*
 	 * if we get to this handler, Nat bits on both r3 and r2 have already
@@ -869,7 +841,7 @@
 	 *
 	 * extract the value to be stored
 	 */
-	getreg(ld->imm, &r2, 0, regs);
+	getreg(ld.imm, &r2, 0, regs);
 
 	/*
 	 * we rely on the macros in unaligned.h for now i.e.,
@@ -879,48 +851,43 @@
 	 * works. The code is optimized by the compiler and looks like
 	 * a single switch/case.
 	 */
-	DPRINT(("st%d [%lx]=%lx\n", len, ifa, r2));
+	DPRINT("st%d [%lx]=%lx\n", len, ifa, r2);
 
-	switch(len) {
-		case 2:
-			ia64_put_unaligned(r2, (void *)ifa, 2);
-			break;
-		case 4:
-			ia64_put_unaligned(r2, (void *)ifa, 4);
-			break;
-		case 8:
-			ia64_put_unaligned(r2, (void *)ifa, 8);
-			break;
-		default:
-			DPRINT(("unknown size: x6=%d\n", ld->x6_sz));
-			return -1;
+	if (len != 2 && len != 4 && len != 8) {
+		DPRINT("unknown size: x6=%d\n", ld.x6_sz);
+		return -1;
 	}
+
+	/* this assumes little-endian byte-order: */
+	if (copy_to_user((void *) ifa, &r2, len))
+		return -1;
+
 	/*
 	 * stX [r3]=r2,imm(9)
 	 *
 	 * NOTE:
-	 * ld->r3 can never be r0, because r0 would not generate an 
+	 * ld.r3 can never be r0, because r0 would not generate an
 	 * unaligned access.
 	 */
-	if (ld->op == 0x5) {
+	if (ld.op == 0x5) {
 		unsigned long imm;
 
 		/*
 		 * form imm9: [12:6] contain first 7bits
 		 */
-		imm = ld->x << 7 | ld->r1;
+		imm = ld.x << 7 | ld.r1;
 		/*
 		 * sign extend (8bits) if m set
 		 */
-		if (ld->m) imm |= SIGN_EXT9; 
+		if (ld.m) imm |= SIGN_EXT9;
 		/*
 		 * ifa == r3 (NaT is necessarily cleared)
 		 */
 		ifa += imm;
 
-		DPRINT(("imm=%lx r3=%lx\n", imm, ifa));
-	
-		setreg(ld->r3, ifa, 0, regs);
+		DPRINT("imm=%lx r3=%lx\n", imm, ifa);
+
+		setreg(ld.r3, ifa, 0, regs);
 	}
 	/*
 	 * we don't have alat_invalidate_multiple() so we need
@@ -931,7 +898,7 @@
 	/*
 	 * stX.rel: use fence instead of release
 	 */
-	if (ld->x6_op == 0xd)
+	if (ld.x6_op == 0xd)
 		mb();
 
 	return 0;
@@ -940,120 +907,108 @@
 /*
  * floating point operations sizes in bytes
  */
-static const unsigned short float_fsz[4]={
+static const unsigned char float_fsz[4]={
 	16, /* extended precision (e) */
 	8,  /* integer (8)            */
 	4,  /* single precision (s)   */
 	8   /* double precision (d)   */
 };
 
-static inline void 
-mem2float_extended(struct ia64_fpreg *init, struct ia64_fpreg *final)
+static inline void
+mem2float_extended (struct ia64_fpreg *init, struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("ldfe f6=[%0];; stf.spill [%1]=f6"
 			      :: "r"(init), "r"(final) : "f6","memory");
 }
 
-static inline void 
-mem2float_integer(struct ia64_fpreg *init, struct ia64_fpreg *final)
+static inline void
+mem2float_integer (struct ia64_fpreg *init, struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("ldf8 f6=[%0];; stf.spill [%1]=f6"
 			      :: "r"(init), "r"(final) : "f6","memory");
 }
 
-static inline void 
-mem2float_single(struct ia64_fpreg *init, struct ia64_fpreg *final)
+static inline void
+mem2float_single (struct ia64_fpreg *init, struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("ldfs f6=[%0];; stf.spill [%1]=f6"
 			      :: "r"(init), "r"(final) : "f6","memory");
 }
 
-static inline void 
-mem2float_double(struct ia64_fpreg *init, struct ia64_fpreg *final)
+static inline void
+mem2float_double (struct ia64_fpreg *init, struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("ldfd f6=[%0];; stf.spill [%1]=f6"
 			      :: "r"(init), "r"(final) : "f6","memory");
 }
 
-static inline void 
-float2mem_extended(struct ia64_fpreg *init, struct ia64_fpreg *final)
+static inline void
+float2mem_extended (struct ia64_fpreg *init, struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("ldf.fill f6=[%0];; stfe [%1]=f6"
 			      :: "r"(init), "r"(final) : "f6","memory");
 }
 
-static inline void 
-float2mem_integer(struct ia64_fpreg *init, struct ia64_fpreg *final)
+static inline void
+float2mem_integer (struct ia64_fpreg *init, struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("ldf.fill f6=[%0];; stf8 [%1]=f6"
 			      :: "r"(init), "r"(final) : "f6","memory");
 }
 
-static inline void 
-float2mem_single(struct ia64_fpreg *init, struct ia64_fpreg *final)
+static inline void
+float2mem_single (struct ia64_fpreg *init, struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("ldf.fill f6=[%0];; stfs [%1]=f6"
 			      :: "r"(init), "r"(final) : "f6","memory");
 }
 
-static inline void 
-float2mem_double(struct ia64_fpreg *init, struct ia64_fpreg *final)
+static inline void
+float2mem_double (struct ia64_fpreg *init, struct ia64_fpreg *final)
 {
 	__asm__ __volatile__ ("ldf.fill f6=[%0];; stfd [%1]=f6"
 			      :: "r"(init), "r"(final) : "f6","memory");
 }
 
 static int
-emulate_load_floatpair(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 {
 	struct ia64_fpreg fpr_init[2];
 	struct ia64_fpreg fpr_final[2];
-	unsigned long len = float_fsz[ld->x6_sz];
+	unsigned long len = float_fsz[ld.x6_sz];
 
-	if (access_ok(VERIFY_READ, (void *)ifa, len<<1) < 0) {
-		DPRINT(("verify area failed on %lx\n", ifa));
-		return -1;
-	}
 	/*
 	 * fr0 & fr1 don't need to be checked because Illegal Instruction
 	 * faults have higher priority than unaligned faults.
 	 *
-	 * r0 cannot be found as the base as it would never generate an 
+	 * r0 cannot be found as the base as it would never generate an
 	 * unaligned reference.
 	 */
 
-	/* 
+	/*
 	 * make sure we get clean buffers
 	 */
-	memset(&fpr_init,0, sizeof(fpr_init));
-	memset(&fpr_final,0, sizeof(fpr_final));
+	memset(&fpr_init, 0, sizeof(fpr_init));
+	memset(&fpr_final, 0, sizeof(fpr_final));
 
 	/*
 	 * ldfpX.a: we don't try to emulate anything but we must
 	 * invalidate the ALAT entry and execute updates, if any.
 	 */
-	if (ld->x6_op != 0x2) {
-		/*
-		 * does the unaligned access
-		 */
-		memcpy(&fpr_init[0], (void *)ifa, len);
-		memcpy(&fpr_init[1], (void *)(ifa+len), len);
+	if (ld.x6_op != 0x2) {
+		/* this assumes little-endian byte-order: */
 
-		DPRINT(("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld->r1, ld->imm, ld->x6_sz));
-#ifdef DEBUG_UNALIGNED_TRAP
-		{ int i; char *c = (char *)&fpr_init;
-			printk("fpr_init= ");
-			for(i=0; i < len<<1; i++ ) {
-				printk("%02x ", c[i]&0xff);
-			}
-			printk("\n");
-		}
-#endif
+		if (copy_from_user(&fpr_init[0], (void *) ifa, len)
+		    || copy_from_user(&fpr_init[1], (void *) (ifa + len), len))
+			return -1;
+
+		DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz);
+		DDUMP("frp_init =", &fpr_init, 2*len);
 		/*
 		 * XXX fixme
-		 * Could optimize inlines by using ldfpX & 2 spills 
+		 * Could optimize inlines by using ldfpX & 2 spills
 		 */
-		switch( ld->x6_sz ) {
+		switch( ld.x6_sz ) {
 			case 0:
 				mem2float_extended(&fpr_init[0], &fpr_final[0]);
 				mem2float_extended(&fpr_init[1], &fpr_final[1]);
@@ -1071,15 +1026,7 @@
 				mem2float_double(&fpr_init[1], &fpr_final[1]);
 				break;
 		}
-#ifdef DEBUG_UNALIGNED_TRAP
-		{ int i; char *c = (char *)&fpr_final;
-			printk("fpr_final= ");
-			for(i=0; i < len<<1; i++ ) {
-				printk("%02x ", c[i]&0xff);
-			}
-			printk("\n");
-		}
-#endif
+		DDUMP("fpr_final =", &fpr_final, 2*len);
 		/*
 		 * XXX fixme
 		 *
@@ -1087,16 +1034,15 @@
 		 * use the storage from the saved context i.e., the actual final
 		 * destination (pt_regs, switch_stack or thread structure).
 		 */
-		setfpreg(ld->r1, &fpr_final[0], regs);
-		setfpreg(ld->imm, &fpr_final[1], regs);
+		setfpreg(ld.r1, &fpr_final[0], regs);
+		setfpreg(ld.imm, &fpr_final[1], regs);
 	}
 
 	/*
 	 * Check for updates: only immediate updates are available for this
 	 * instruction.
 	 */
-	if (ld->m) {
-
+	if (ld.m) {
 		/*
 		 * the immediate is implicit given the ldsz of the operation:
 		 * single: 8 (2x4) and for  all others it's 16 (2x8)
@@ -1104,57 +1050,45 @@
 		ifa += len<<1;
 
 		/*
-		 * IMPORTANT: 
+		 * IMPORTANT:
 		 * the fact that we force the NaT of r3 to zero is ONLY valid
 		 * as long as we don't come here with a ldfpX.s.
 		 * For this reason we keep this sanity check
 		 */
-		if (ld->x6_op == 1 || ld->x6_op == 3) {
-			printk(KERN_ERR "%s: register update on speculative load pair, error\n",
-			       __FUNCTION__);	
-		}
-
+		if (ld.x6_op == 1 || ld.x6_op == 3)
+			printk(KERN_ERR __FUNCTION__": register update on speculative load pair, "
+			       "error\n");
 
-		setreg(ld->r3, ifa, 0, regs);
+		setreg(ld.r3, ifa, 0, regs);
 	}
 
 	/*
 	 * Invalidate ALAT entries, if any, for both registers.
 	 */
-	if (ld->x6_op == 0x2) {
-		invala_fr(ld->r1);
-		invala_fr(ld->imm);
+	if (ld.x6_op == 0x2) {
+		invala_fr(ld.r1);
+		invala_fr(ld.imm);
 	}
 	return 0;
 }
 
 
 static int
-emulate_load_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 {
 	struct ia64_fpreg fpr_init;
 	struct ia64_fpreg fpr_final;
-	unsigned long len = float_fsz[ld->x6_sz];
+	unsigned long len = float_fsz[ld.x6_sz];
 
 	/*
-	 * check for load pair because our masking scheme is not fine grain enough
-	if (ld->x == 1) return emulate_load_floatpair(ifa,ld,regs);
-	 */
-
-	if (access_ok(VERIFY_READ, (void *)ifa, len) < 0) {
-		DPRINT(("verify area failed on %lx\n", ifa));
-		return -1;
-	}
-	/*
 	 * fr0 & fr1 don't need to be checked because Illegal Instruction
 	 * faults have higher priority than unaligned faults.
 	 *
-	 * r0 cannot be found as the base as it would never generate an 
+	 * r0 cannot be found as the base as it would never generate an
 	 * unaligned reference.
 	 */
 
-
-	/* 
+	/*
 	 * make sure we get clean buffers
 	 */
 	memset(&fpr_init,0, sizeof(fpr_init));
@@ -1165,27 +1099,16 @@
 	 * invalidate the ALAT entry.
 	 * See comments in ldX for descriptions on how the various loads are handled.
 	 */
-	if (ld->x6_op != 0x2) {
-
-		/*
-		 * does the unaligned access
-		 */
-		memcpy(&fpr_init, (void *)ifa, len);
+	if (ld.x6_op != 0x2) {
+		if (copy_from_user(&fpr_init, (void *) ifa, len))
+			return -1;
 
-		DPRINT(("ld.r1=%d x6_sz=%d\n", ld->r1, ld->x6_sz));
-#ifdef DEBUG_UNALIGNED_TRAP
-		{ int i; char *c = (char *)&fpr_init;
-			printk("fpr_init= ");
-			for(i=0; i < len; i++ ) {
-				printk("%02x ", c[i]&0xff);
-			}
-			printk("\n");
-		}
-#endif
+		DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz);
+		DDUMP("fpr_init =", &fpr_init, len);
 		/*
 		 * we only do something for x6_op={0,8,9}
 		 */
-		switch( ld->x6_sz ) {
+		switch( ld.x6_sz ) {
 			case 0:
 				mem2float_extended(&fpr_init, &fpr_final);
 				break;
@@ -1199,15 +1122,7 @@
 				mem2float_double(&fpr_init, &fpr_final);
 				break;
 		}
-#ifdef DEBUG_UNALIGNED_TRAP
-		{ int i; char *c = (char *)&fpr_final;
-			printk("fpr_final= ");
-			for(i=0; i < len; i++ ) {
-				printk("%02x ", c[i]&0xff);
-			}
-			printk("\n");
-		}
-#endif
+		DDUMP("fpr_final =", &fpr_final, len);
 		/*
 		 * XXX fixme
 		 *
@@ -1215,66 +1130,51 @@
 		 * use the storage from the saved context i.e., the actual final
 		 * destination (pt_regs, switch_stack or thread structure).
 		 */
-		setfpreg(ld->r1, &fpr_final, regs);
+		setfpreg(ld.r1, &fpr_final, regs);
 	}
 
 	/*
 	 * check for updates on any loads
 	 */
-	if (ld->op == 0x7 || ld->m)
-		emulate_load_updates(ld->op == 0x7 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa);
+	if (ld.op == 0x7 || ld.m)
+		emulate_load_updates(ld.op == 0x7 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa);
 
 	/*
 	 * invalidate ALAT entry in case of advanced floating point loads
 	 */
-	if (ld->x6_op == 0x2)
-		invala_fr(ld->r1);
+	if (ld.x6_op == 0x2)
+		invala_fr(ld.r1);
 
 	return 0;
 }
 
 
 static int
-emulate_store_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 {
 	struct ia64_fpreg fpr_init;
 	struct ia64_fpreg fpr_final;
-	unsigned long len = float_fsz[ld->x6_sz];
-	
-	/*
-	 * the macro supposes sequential access (which is the case)
-	 * if the first byte is an invalid address we return here. Otherwise
-	 * there is a guard page at the top of the user's address page and 
-	 * the first access would generate a NaT consumption fault and return
-	 * with a SIGSEGV, which is what we want.
-	 *
-	 * Note: the first argument is ignored 
-	 */
-	if (access_ok(VERIFY_WRITE, (void *)ifa, len) < 0) {
-		DPRINT(("verify area failed on %lx\n",ifa));
-		return -1;
-	}
+	unsigned long len = float_fsz[ld.x6_sz];
 
-	/* 
+	/*
 	 * make sure we get clean buffers
 	 */
 	memset(&fpr_init,0, sizeof(fpr_init));
 	memset(&fpr_final,0, sizeof(fpr_final));
 
-
 	/*
 	 * if we get to this handler, Nat bits on both r3 and r2 have already
 	 * been checked. so we don't need to do it
 	 *
 	 * extract the value to be stored
 	 */
-	getfpreg(ld->imm, &fpr_init, regs);
+	getfpreg(ld.imm, &fpr_init, regs);
 	/*
 	 * during this step, we extract the spilled registers from the saved
 	 * context i.e., we refill. Then we store (no spill) to temporary
 	 * aligned location
 	 */
-	switch( ld->x6_sz ) {
+	switch( ld.x6_sz ) {
 		case 0:
 			float2mem_extended(&fpr_init, &fpr_final);
 			break;
@@ -1288,56 +1188,40 @@
 			float2mem_double(&fpr_init, &fpr_final);
 			break;
 	}
-	DPRINT(("ld.r1=%d x6_sz=%d\n", ld->r1, ld->x6_sz));
-#ifdef DEBUG_UNALIGNED_TRAP
-		{ int i; char *c = (char *)&fpr_init;
-			printk("fpr_init= ");
-			for(i=0; i < len; i++ ) {
-				printk("%02x ", c[i]&0xff);
-			}
-			printk("\n");
-		}
-		{ int i; char *c = (char *)&fpr_final;
-			printk("fpr_final= ");
-			for(i=0; i < len; i++ ) {
-				printk("%02x ", c[i]&0xff);
-			}
-			printk("\n");
-		}
-#endif
+	DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz);
+	DDUMP("fpr_init =", &fpr_init, len);
+	DDUMP("fpr_final =", &fpr_final, len);
 
-	/*
-	 * does the unaligned store
-	 */
-	memcpy((void *)ifa, &fpr_final, len);
+	if (copy_to_user((void *) ifa, &fpr_final, len))
+		return -1;
 
 	/*
 	 * stfX [r3]=r2,imm(9)
 	 *
 	 * NOTE:
-	 * ld->r3 can never be r0, because r0 would not generate an 
+	 * ld.r3 can never be r0, because r0 would not generate an
 	 * unaligned access.
 	 */
-	if (ld->op == 0x7) {
+	if (ld.op == 0x7) {
 		unsigned long imm;
 
 		/*
 		 * form imm9: [12:6] contain first 7bits
 		 */
-		imm = ld->x << 7 | ld->r1;
+		imm = ld.x << 7 | ld.r1;
 		/*
 		 * sign extend (8bits) if m set
 		 */
-		if (ld->m)
-			imm |= SIGN_EXT9; 
+		if (ld.m)
+			imm |= SIGN_EXT9;
 		/*
 		 * ifa == r3 (NaT is necessarily cleared)
 		 */
 		ifa += imm;
 
-		DPRINT(("imm=%lx r3=%lx\n", imm, ifa));
-	
-		setreg(ld->r3, ifa, 0, regs);
+		DPRINT("imm=%lx r3=%lx\n", imm, ifa);
+
+		setreg(ld.r3, ifa, 0, regs);
 	}
 	/*
 	 * we don't have alat_invalidate_multiple() so we need
@@ -1348,132 +1232,106 @@
 	return 0;
 }
 
-void
-ia64_handle_unaligned(unsigned long ifa, struct pt_regs *regs)
+/*
+ * Make sure we log the unaligned access, so that user/sysadmin can notice it and
+ * eventually fix the program.  However, we don't want to do that for every access so we
+ * pace it with jiffies.  This isn't really MP-safe, but it doesn't really have to be
+ * either...
+ */
+static int
+within_logging_rate_limit (void)
 {
-	static unsigned long unalign_count;
-	static long last_time;
+	static unsigned long count, last_time;
 
+	if (jiffies - last_time > 5*HZ)
+		count = 0;
+	if (++count < 5) {
+		last_time = jiffies;
+		return 1;
+	}
+	return 0;
+
+}
+
+void
+ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
+{
+	struct exception_fixup fix = { 0 };
 	struct ia64_psr *ipsr = ia64_psr(regs);
-	unsigned long *bundle_addr;
+	mm_segment_t old_fs = get_fs();
+	unsigned long bundle[2];
 	unsigned long opcode;
-	unsigned long op;
-	load_store_t *insn;
+	struct siginfo si;
+	union {
+		unsigned long l;
+		load_store_t insn;
+	} u;
 	int ret = -1;
 
+	if (ia64_psr(regs)->be) {
+		/* we don't support big-endian accesses */
+		die_if_kernel("big-endian unaligned accesses are not supported", regs, 0);
+		goto force_sigbus;
+	}
+
 	/*
-	 * Unaligned references in the kernel could come from unaligned
-	 *   arguments to system calls.  We fault the user process in
-	 *   these cases and panic the kernel otherwise (the kernel should
-	 *   be fixed to not make unaligned accesses).
+	 * Treat kernel accesses for which there is an exception handler entry the same as
+	 * user-level unaligned accesses.  Otherwise, a clever program could trick this
+	 * handler into reading an arbitrary kernel addresses...
 	 */
 	if (!user_mode(regs)) {
-		const struct exception_table_entry *fix;
-
+#ifdef GAS_HAS_LOCAL_TAGS
+		fix = search_exception_table(regs->cr_iip + ia64_psr(regs)->ri);
+#else
 		fix = search_exception_table(regs->cr_iip);
-		if (fix) {
-			regs->r8 = -EFAULT;
-			if (fix->skip & 1) {
-				regs->r9 = 0;
-			}
-			regs->cr_iip += ((long) fix->skip) & ~15;
-			regs->cr_ipsr &= ~IA64_PSR_RI;	/* clear exception slot number */
-			return;
-		}
-		die_if_kernel("Unaligned reference while in kernel\n", regs, 30);
-		/* NOT_REACHED */
-	}
-	/*
-	 * For now, we don't support user processes running big-endian
-	 * which do unaligned accesses
-	 */
-	if (ia64_psr(regs)->be) {
-		struct siginfo si;
-
-		printk(KERN_ERR "%s(%d): big-endian unaligned access %016lx (ip=%016lx) not "
-		       "yet supported\n",
-		       current->comm, current->pid, ifa, regs->cr_iip + ipsr->ri);
-
-		si.si_signo = SIGBUS;
-		si.si_errno = 0;
-		si.si_code = BUS_ADRALN;
-		si.si_addr = (void *) ifa;
-		force_sig_info(SIGBUS, &si, current);
-		return;
-	}
-
-	if (current->thread.flags & IA64_THREAD_UAC_SIGBUS) {
-		struct siginfo si;
-
-		si.si_signo = SIGBUS;
-		si.si_errno = 0;
-		si.si_code = BUS_ADRALN;
-		si.si_addr = (void *) ifa;
-		force_sig_info(SIGBUS, &si, current);
-		return;
+#endif
 	}
-
-	if (!(current->thread.flags & IA64_THREAD_UAC_NOPRINT)) {
-		/*
-		 * Make sure we log the unaligned access, so that
-		 * user/sysadmin can notice it and eventually fix the
-		 * program.
-		 *
-		 * We don't want to do that for every access so we
-		 * pace it with jiffies.
-		 */
-		if (unalign_count > 5 && jiffies - last_time > 5*HZ)
-			unalign_count = 0;
-		if (++unalign_count < 5) {
+	if (user_mode(regs) || fix.cont) {
+		if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0)
+			goto force_sigbus;
+
+		if (!(current->thread.flags & IA64_THREAD_UAC_NOPRINT)
+		    && within_logging_rate_limit())
+		{
 			char buf[200];	/* comm[] is at most 16 bytes... */
 			size_t len;
 
-			last_time = jiffies;
-			len = sprintf(buf, "%s(%d): unaligned access to 0x%016lx, ip=0x%016lx\n\r",
-				      current->comm, current->pid, ifa, regs->cr_iip + ipsr->ri);
+			len = sprintf(buf, "%s(%d): unaligned access to 0x%016lx, "
+				      "ip=0x%016lx\n\r", current->comm, current->pid,
+				      ifa, regs->cr_iip + ipsr->ri);
 			tty_write_message(current->tty, buf);
 			buf[len-1] = '\0';	/* drop '\r' */
-			printk("%s", buf);	/* guard against command names containing %s!! */
+			printk(KERN_WARNING "%s", buf);	/* watch for command names containing %s */
 		}
+	} else {
+		if (within_logging_rate_limit())
+			printk(KERN_WARNING "kernel unaligned access to 0x%016lx, ip=0x%016lx\n",
+			       ifa, regs->cr_iip + ipsr->ri);
+		set_fs(KERNEL_DS);
 	}
 
-	DPRINT(("iip=%lx ifa=%lx isr=%lx\n", regs->cr_iip, ifa, regs->cr_ipsr));
-	DPRINT(("ISR.ei=%d ISR.sp=%d\n", ipsr->ri, ipsr->it));
+	DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n",
+	       regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it);
 
-	bundle_addr = (unsigned long *)(regs->cr_iip);
+	if (__copy_from_user(bundle, (void *) regs->cr_iip, 16))
+		goto failure;
 
 	/*
 	 * extract the instruction from the bundle given the slot number
 	 */
-	switch ( ipsr->ri ) {
-		case 0: op = *bundle_addr >> 5;
-			break;
-
-		case 1: op = *bundle_addr >> 46 | (*(bundle_addr+1) & 0x7fffff)<<18;
-			break;
-
-		case 2: op = *(bundle_addr+1) >> 23;
-		 	break;
+	switch (ipsr->ri) {
+	      case 0: u.l = (bundle[0] >>  5); break;
+	      case 1: u.l = (bundle[0] >> 46) | (bundle[1] << 18); break;
+	      case 2: u.l = (bundle[1] >> 23); break;
 	}
+	opcode = (u.l >> IA64_OPCODE_SHIFT) & IA64_OPCODE_MASK;
 
-	insn   = (load_store_t *)&op;
-	opcode = op & IA64_OPCODE_MASK;
-
-	DPRINT(("opcode=%lx ld.qp=%d ld.r1=%d ld.imm=%d ld.r3=%d ld.x=%d ld.hint=%d "
-		"ld.x6=0x%x ld.m=%d ld.op=%d\n",
-		opcode,
-		insn->qp,
-		insn->r1,
-		insn->imm,
-		insn->r3,
-		insn->x,
-		insn->hint,
-		insn->x6_sz,
-		insn->m,
-		insn->op));
+	DPRINT("opcode=%lx ld.qp=%d ld.r1=%d ld.imm=%d ld.r3=%d ld.x=%d ld.hint=%d "
+	       "ld.x6=0x%x ld.m=%d ld.op=%d\n", opcode, u.insn.qp, u.insn.r1, u.insn.imm,
+	       u.insn.r3, u.insn.x, u.insn.hint, u.insn.x6_sz, u.insn.m, u.insn.op);
 
 	/*
-  	 * IMPORTANT:
+	 * IMPORTANT:
 	 * Notice that the swictch statement DOES not cover all possible instructions
 	 * that DO generate unaligned references. This is made on purpose because for some
 	 * instructions it DOES NOT make sense to try and emulate the access. Sometimes it
@@ -1483,104 +1341,124 @@
 	 *	load/store:
 	 *		- ldX.spill
 	 *		- stX.spill
-	 * 	Reason: RNATs are based on addresses
+	 *	Reason: RNATs are based on addresses
 	 *
 	 *	synchronization:
 	 *		- cmpxchg
 	 *		- fetchadd
 	 *		- xchg
-	 * 	Reason: ATOMIC operations cannot be emulated properly using multiple 
-	 * 	        instructions.
+	 *	Reason: ATOMIC operations cannot be emulated properly using multiple
+	 *	        instructions.
 	 *
 	 *	speculative loads:
 	 *		- ldX.sZ
-	 *	Reason: side effects, code must be ready to deal with failure so simpler 
-	 * 		to let the load fail.
+	 *	Reason: side effects, code must be ready to deal with failure so simpler
+	 *		to let the load fail.
 	 * ---------------------------------------------------------------------------------
 	 * XXX fixme
 	 *
 	 * I would like to get rid of this switch case and do something
 	 * more elegant.
 	 */
-	switch(opcode) {
-		case LDS_OP:
-		case LDSA_OP:
-		case LDS_IMM_OP:
-		case LDSA_IMM_OP:
-		case LDFS_OP:
-		case LDFSA_OP:
-		case LDFS_IMM_OP:
-			/*
-			 * The instruction will be retried with defered exceptions
-			 * turned on, and we should get Nat bit installed
-			 *
-			 * IMPORTANT:
-			 * When PSR_ED is set, the register & immediate update
-			 * forms are actually executed even though the operation
-			 * failed. So we don't need to take care of this.
-			 */
-			DPRINT(("forcing PSR_ED\n"));
-			regs->cr_ipsr |= IA64_PSR_ED;
-			return;
-
-		case LD_OP:
-		case LDA_OP:
-		case LDBIAS_OP:
-		case LDACQ_OP:
-		case LDCCLR_OP:
-		case LDCNC_OP:
-		case LDCCLRACQ_OP:
-		case LD_IMM_OP:
-		case LDA_IMM_OP:
-		case LDBIAS_IMM_OP:
-		case LDACQ_IMM_OP:
-		case LDCCLR_IMM_OP:
-		case LDCNC_IMM_OP:
-		case LDCCLRACQ_IMM_OP:
-			ret = emulate_load_int(ifa, insn, regs);
-			break;
-		case ST_OP:
-		case STREL_OP:
-		case ST_IMM_OP:
-		case STREL_IMM_OP:
-			ret = emulate_store_int(ifa, insn, regs);
-			break;
-		case LDF_OP:
-		case LDFA_OP:
-		case LDFCCLR_OP:
-		case LDFCNC_OP:
-		case LDF_IMM_OP:
-		case LDFA_IMM_OP:
-		case LDFCCLR_IMM_OP:
-		case LDFCNC_IMM_OP:
-			ret = insn->x ? 
-			      emulate_load_floatpair(ifa, insn, regs):
-			      emulate_load_float(ifa, insn, regs);
-			break;
-		case STF_OP:
-		case STF_IMM_OP:
-			ret = emulate_store_float(ifa, insn, regs);
-	}
-
-	DPRINT(("ret=%d\n", ret));
-	if (ret) {
-		struct siginfo si;
-
-		si.si_signo = SIGBUS;
-		si.si_errno = 0;
-		si.si_code = BUS_ADRALN;
-		si.si_addr = (void *) ifa;
-	        force_sig_info(SIGBUS, &si, current);
-	} else {
+	switch (opcode) {
+	      case LDS_OP:
+	      case LDSA_OP:
+	      case LDS_IMM_OP:
+	      case LDSA_IMM_OP:
+	      case LDFS_OP:
+	      case LDFSA_OP:
+	      case LDFS_IMM_OP:
 		/*
-	 	 * given today's architecture this case is not likely to happen
-	 	 * because a memory access instruction (M) can never be in the 
-	 	 * last slot of a bundle. But let's keep it for  now.
-	 	 */
-		if (ipsr->ri == 2)
-			regs->cr_iip += 16;
-		ipsr->ri = ++ipsr->ri & 3;
-	}
+		 * The instruction will be retried with deferred exceptions turned on, and
+		 * we should get Nat bit installed
+		 *
+		 * IMPORTANT: When PSR_ED is set, the register & immediate update forms
+		 * are actually executed even though the operation failed. So we don't
+		 * need to take care of this.
+		 */
+		DPRINT("forcing PSR_ED\n");
+		regs->cr_ipsr |= IA64_PSR_ED;
+		goto done;
+
+	      case LD_OP:
+	      case LDA_OP:
+	      case LDBIAS_OP:
+	      case LDACQ_OP:
+	      case LDCCLR_OP:
+	      case LDCNC_OP:
+	      case LDCCLRACQ_OP:
+	      case LD_IMM_OP:
+	      case LDA_IMM_OP:
+	      case LDBIAS_IMM_OP:
+	      case LDACQ_IMM_OP:
+	      case LDCCLR_IMM_OP:
+	      case LDCNC_IMM_OP:
+	      case LDCCLRACQ_IMM_OP:
+		ret = emulate_load_int(ifa, u.insn, regs);
+		break;
+
+	      case ST_OP:
+	      case STREL_OP:
+	      case ST_IMM_OP:
+	      case STREL_IMM_OP:
+		ret = emulate_store_int(ifa, u.insn, regs);
+		break;
+
+	      case LDF_OP:
+	      case LDFA_OP:
+	      case LDFCCLR_OP:
+	      case LDFCNC_OP:
+	      case LDF_IMM_OP:
+	      case LDFA_IMM_OP:
+	      case LDFCCLR_IMM_OP:
+	      case LDFCNC_IMM_OP:
+		if (u.insn.x)
+			ret = emulate_load_floatpair(ifa, u.insn, regs);
+		else
+			ret = emulate_load_float(ifa, u.insn, regs);
+		break;
+
+	      case STF_OP:
+	      case STF_IMM_OP:
+		ret = emulate_store_float(ifa, u.insn, regs);
+		break;
+
+	      default:
+		goto failure;
+	}
+	DPRINT("ret=%d\n", ret);
+	if (ret)
+		goto failure;
+
+	if (ipsr->ri == 2)
+		/*
+		 * given today's architecture this case is not likely to happen because a
+		 * memory access instruction (M) can never be in the last slot of a
+		 * bundle. But let's keep it for now.
+		 */
+		regs->cr_iip += 16;
+	ipsr->ri = (ipsr->ri + 1) & 0x3;
+
+	DPRINT("ipsr->ri=%d iip=%lx\n", ipsr->ri, regs->cr_iip);
+  done:
+	set_fs(old_fs);		/* restore original address limit */
+	return;
 
-	DPRINT(("ipsr->ri=%d iip=%lx\n", ipsr->ri, regs->cr_iip));
+  failure:
+	/* something went wrong... */
+	if (!user_mode(regs)) {
+		if (fix.cont) {
+			handle_exception(regs, fix);
+			goto done;
+		}
+		die_if_kernel("error during unaligned kernel access\n", regs, ret);
+		/* NOT_REACHED */
+	}
+  force_sigbus:
+	si.si_signo = SIGBUS;
+	si.si_errno = 0;
+	si.si_code = BUS_ADRALN;
+	si.si_addr = (void *) ifa;
+	force_sig_info(SIGBUS, &si, current);
+	goto done;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/kernel/unwind.c linux/arch/ia64/kernel/unwind.c
--- v2.4.3/linux/arch/ia64/kernel/unwind.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/ia64/kernel/unwind.c	Thu Apr 12 12:16:35 2001
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 /*
  * This file implements call frame unwind support for the Linux
@@ -24,15 +24,12 @@
  *	o if both the unw.lock spinlock and a script's read-write lock must be
  *	  acquired, then the read-write lock must be acquired first.
  */
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 
 #include <asm/unwind.h>
 
-#ifdef CONFIG_IA64_NEW_UNWIND
-
 #include <asm/delay.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -306,7 +303,7 @@
 		}
 	} else {
 		/* access a stacked register */
-		addr = ia64_rse_skip_regs((unsigned long *) info->bsp, regnum);
+		addr = ia64_rse_skip_regs((unsigned long *) info->bsp, regnum - 32);
 		nat_addr = ia64_rse_rnat_addr(addr);
 		if ((unsigned long) addr < info->regstk.limit
 		    || (unsigned long) addr >= info->regstk.top)
@@ -660,7 +657,7 @@
 	 */
 	if (sr->any_spills) {
 		off = sr->spill_offset;
-		alloc_spill_area(&off, 16, sr->curr.reg + UNW_REG_F2, sr->curr.reg + UNW_REG_F31); 
+		alloc_spill_area(&off, 16, sr->curr.reg + UNW_REG_F2, sr->curr.reg + UNW_REG_F31);
 		alloc_spill_area(&off,  8, sr->curr.reg + UNW_REG_B1, sr->curr.reg + UNW_REG_B5);
 		alloc_spill_area(&off,  8, sr->curr.reg + UNW_REG_R4, sr->curr.reg + UNW_REG_R7);
 	}
@@ -911,6 +908,10 @@
 	struct unw_reg_state *rs;
 
 	rs = alloc_reg_state();
+	if (!rs) {
+		printk("unwind: cannot stack!\n");
+		return;
+	}
 	memcpy(rs, &sr->curr, sizeof(*rs));
 	rs->label = label;
 	rs->next = sr->reg_state_list;
@@ -927,7 +928,7 @@
 	if (sr->when_target <= sr->region_start + MIN((int)t, sr->region_len - 1))
 		return 0;
 	if (qp > 0) {
-		if ((sr->pr_val & (1UL << qp)) == 0) 
+		if ((sr->pr_val & (1UL << qp)) == 0)
 			return 0;
 		sr->pr_mask |= (1UL << qp);
 	}
@@ -944,7 +945,7 @@
 
 	r = sr->curr.reg + decode_abreg(abreg, 0);
 	r->where = UNW_WHERE_NONE;
-	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	r->when = UNW_WHEN_NEVER;
 	r->val = 0;
 }
 
@@ -1443,12 +1444,17 @@
 		 * sp has been restored and all values on the memory stack below
 		 * psp also have been restored.
 		 */
-		sr.curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
 		sr.curr.reg[UNW_REG_PSP].val = 0;
+		sr.curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
+		sr.curr.reg[UNW_REG_PSP].when = UNW_WHEN_NEVER;
 		for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r)
 			if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)
 			    || r->where == UNW_WHERE_SPREL)
+			{
+				r->val = 0;
 				r->where = UNW_WHERE_NONE;
+				r->when = UNW_WHEN_NEVER;
+			}
 	}
 
 	script->flags = sr.flags;
@@ -1477,7 +1483,7 @@
 			      case UNW_WHERE_PSPREL: printk("[psp+0x%lx]", r->val); break;
 			      case UNW_WHERE_NONE:
 				printk("%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
-				break; 
+				break;
 			      default:		     printk("BADWHERE(%d)", r->where); break;
 			}
 			printk("\t\t%d\n", r->when);
@@ -1604,7 +1610,9 @@
 
 		      case UNW_INSN_LOAD:
 #if UNW_DEBUG
-			if ((s[val] & (my_cpu_data.unimpl_va_mask | 0x7)) || s[val] < TASK_SIZE) {
+			if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0
+			    || s[val] < TASK_SIZE)
+			{
 				debug(1, "unwind: rejecting bad psp=0x%lx\n", s[val]);
 				break;
 			}
@@ -1636,7 +1644,7 @@
 	int have_write_lock = 0;
 	struct unw_script *scr;
 
-	if ((info->ip & (my_cpu_data.unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
+	if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
 		/* don't let obviously bad addresses pollute the cache */
 		debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip);
 		info->rp_loc = 0;
@@ -1672,7 +1680,7 @@
 	unsigned long ip, pr, num_regs;
 	STAT(unsigned long start, flags;)
 	int retval;
-	
+
 	STAT(local_irq_save(flags); ++unw.stat.api.unwinds; start = ia64_get_itc());
 
 	prev_ip = info->ip;
@@ -1818,140 +1826,14 @@
 	STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
 }
 
-#endif /* CONFIG_IA64_NEW_UNWIND */
-
 void
 unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t)
 {
 	struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16);
 
-#ifdef CONFIG_IA64_NEW_UNWIND
 	unw_init_frame_info(info, t, sw);
-#else
-	unsigned long sol, limit, top;
-
-	memset(info, 0, sizeof(*info));
-
-	sol = (sw->ar_pfs >> 7) & 0x7f;	/* size of locals */
-
-	limit = (unsigned long) t + IA64_RBS_OFFSET;
-	top   = sw->ar_bspstore;
-	if (top - (unsigned long) t >= IA64_STK_OFFSET)
-		top = limit;
-
-	info->regstk.limit = limit;
-	info->regstk.top   = top;
-	info->sw  = sw;
-	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol);
-	info->cfm_loc = &sw->ar_pfs;
-	info->ip  = sw->b0;
-#endif
 }
 
-void
-unw_init_from_current (struct unw_frame_info *info, struct pt_regs *regs)
-{
-#ifdef CONFIG_IA64_NEW_UNWIND
-	struct switch_stack *sw = (struct switch_stack *) regs - 1;
-
-	unw_init_frame_info(info, current, sw);
-	/* skip over interrupt frame: */
-	unw_unwind(info);
-#else
-	struct switch_stack *sw = (struct switch_stack *) regs - 1;
-	unsigned long sol, sof, *bsp, limit, top;
-
-	limit = (unsigned long) current + IA64_RBS_OFFSET;
-	top   = sw->ar_bspstore;
-	if (top - (unsigned long) current >= IA64_STK_OFFSET)
-		top = limit;
-
-	memset(info, 0, sizeof(*info));
-
-	sol = (sw->ar_pfs >> 7) & 0x7f;	/* size of frame */
-
-	/* this gives us the bsp top level frame (kdb interrupt frame): */
-	bsp = ia64_rse_skip_regs((unsigned long *) top, -sol);
-
-	/* now skip past the interrupt frame: */
-	sof = regs->cr_ifs & 0x7f;	/* size of frame */
-
-	info->regstk.limit = limit;
-	info->regstk.top   = top;
-	info->sw = sw;
-	info->bsp = (unsigned long) ia64_rse_skip_regs(bsp, -sof);
-	info->cfm_loc = &regs->cr_ifs;
-	info->ip  = regs->cr_iip;
-#endif
-}
-
-#ifndef CONFIG_IA64_NEW_UNWIND
-
-static unsigned long
-read_reg (struct unw_frame_info *info, int regnum, int *is_nat)
-{
-	unsigned long *addr, *rnat_addr, rnat;
-
-	addr = ia64_rse_skip_regs((unsigned long *) info->bsp, regnum);
-	if ((unsigned long) addr < info->regstk.limit
-	    || (unsigned long) addr >= info->regstk.top || ((long) addr & 0x7) != 0)
-	{
-		*is_nat = 1;
-		return 0xdeadbeefdeadbeef;
-	}
-	rnat_addr = ia64_rse_rnat_addr(addr);
-
-	if ((unsigned long) rnat_addr >= info->regstk.top)
-		rnat = info->sw->ar_rnat;
-	else
-		rnat = *rnat_addr;
-	*is_nat = (rnat & (1UL << ia64_rse_slot_num(addr))) != 0;
-	return *addr;
-}
-
-/*
- * On entry, info->regstk.top should point to the register backing
- * store for r32.
- */
-int
-unw_unwind (struct unw_frame_info *info)
-{
-	unsigned long sol, cfm = *info->cfm_loc;
-	int is_nat;
-
-	sol = (cfm >> 7) & 0x7f;	/* size of locals */
-
-	/*
-	 * In general, we would have to make use of unwind info to
-	 * unwind an IA-64 stack, but for now gcc uses a special
-	 * convention that makes this possible without full-fledged
-	 * unwindo info.  Specifically, we expect "rp" in the second
-	 * last, and "ar.pfs" in the last local register, so the
-	 * number of locals in a frame must be at least two.  If it's
-	 * less than that, we reached the end of the C call stack.
-	 */
-	if (sol < 2)
-		return -1;
-
-	info->ip = read_reg(info, sol - 2, &is_nat);
-	if (is_nat || (info->ip & (my_cpu_data.unimpl_va_mask | 0xf)))
-		/* reject let obviously bad addresses */
-		return -1;
-
-	info->cfm_loc = ia64_rse_skip_regs((unsigned long *) info->bsp, sol - 1);
-	cfm = read_reg(info, sol - 1, &is_nat);
-	if (is_nat)
-		return -1;
-
-	sol = (cfm >> 7) & 0x7f;
-
-	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -sol);
-	return 0;
-}
-#endif /* !CONFIG_IA64_NEW_UNWIND */
-
-#ifdef CONFIG_IA64_NEW_UNWIND
-
 static void
 init_unwind_table (struct unw_table *table, const char *name, unsigned long segment_base,
 		   unsigned long gp, void *table_start, void *table_end)
@@ -1979,7 +1861,7 @@
 		dprintk("unwind: ignoring attempt to insert empty unwind table\n");
 		return 0;
 	}
-	
+
 	table = kmalloc(sizeof(*table), GFP_USER);
 	if (!table)
 		return 0;
@@ -2052,12 +1934,10 @@
 
 	kfree(table);
 }
-#endif /* CONFIG_IA64_NEW_UNWIND */
 
 void
 unw_init (void)
 {
-#ifdef CONFIG_IA64_NEW_UNWIND
 	extern int ia64_unw_start, ia64_unw_end, __gp;
 	extern void unw_hash_index_t_is_too_narrow (void);
 	long i, off;
@@ -2093,5 +1973,4 @@
 
 	init_unwind_table(&unw.kernel_table, "kernel", KERNEL_START, (unsigned long) &__gp,
 			  &ia64_unw_start, &ia64_unw_end);
-#endif /* CONFIG_IA64_NEW_UNWIND */
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/Makefile linux/arch/ia64/lib/Makefile
--- v2.4.3/linux/arch/ia64/lib/Makefile	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/lib/Makefile	Thu Apr  5 12:51:47 2001
@@ -7,18 +7,18 @@
 
 L_TARGET = lib.a
 
+export-objs := io.o swiotlb.o
+
 obj-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o					\
 	__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o					\
 	checksum.o clear_page.o csum_partial_copy.o copy_page.o				\
 	copy_user.o clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o	\
-	flush.o do_csum.o								\
+	flush.o io.o do_csum.o								\
 	swiotlb.o
 
 ifneq ($(CONFIG_ITANIUM_ASTEP_SPECIFIC),y)
   obj-y += memcpy.o memset.o strlen.o
 endif
-
-export-objs += io.o
 
 IGNORE_FLAGS_OBJS =	__divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
 			__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/clear_page.S linux/arch/ia64/lib/clear_page.S
--- v2.4.3/linux/arch/ia64/lib/clear_page.S	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/lib/clear_page.S	Thu Apr  5 12:51:47 2001
@@ -6,29 +6,24 @@
  *
  * Inputs:
  *	in0:	address of page
- * 
+ *
  * Output:
  * 	none
  *
- * Copyright (C) 1999-2000 Hewlett-Packard Co
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
  * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #include <asm/asmmacro.h>
 #include <asm/page.h>
 
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 GLOBAL_ENTRY(clear_page)
-	UNW(.prologue)
+	.prologue
 	alloc r11=ar.pfs,1,0,0,0
-	UNW(.save ar.lc, r16)
+	.save ar.lc, r16
 	mov r16=ar.lc		// slow
 
-	UNW(.body)
+	.body
 
 	mov r17=PAGE_SIZE/32-1	// -1 = repeat/until
 	;;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/clear_user.S linux/arch/ia64/lib/clear_user.S
--- v2.4.3/linux/arch/ia64/lib/clear_user.S	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/lib/clear_user.S	Thu Apr  5 12:51:47 2001
@@ -6,8 +6,8 @@
  *	in1:	length of buffer in bytes
  * Outputs:
  *	r8:	number of bytes that didn't get cleared due to a fault
- * 
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ *
+ * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
  * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
  */
 
@@ -51,27 +51,12 @@
 //	have side effects (same thing for writing).
 //
 
-// The label comes first because our store instruction contains a comma
-// and confuse the preprocessor otherwise
-//
-#define EX(y,x...)				\
-	.section __ex_table,"a";		\
-	data4 @gprel(99f);			\
-	data4 y-99f;				\
-	.previous;				\
-99:	x
-
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 GLOBAL_ENTRY(__do_clear_user)
-	UNW(.prologue)
-	UNW(.save ar.pfs, saved_pfs)
- 	alloc	saved_pfs=ar.pfs,2,0,0,0
+	.prologue
+	.save ar.pfs, saved_pfs
+	alloc	saved_pfs=ar.pfs,2,0,0,0
 	cmp.eq p6,p0=r0,len		// check for zero length
-	UNW(.save ar.lc, saved_lc)
+	.save ar.lc, saved_lc
 	mov saved_lc=ar.lc		// preserve ar.lc (slow)
 	.body
 	;;				// avoid WAW on CFM
@@ -80,7 +65,7 @@
 (p6)	br.ret.spnt.few rp
 	;;
 	cmp.lt p6,p0=16,len		// if len > 16 then long memset
-	mov ar.lc=tmp			// initialize lc for small count 
+	mov ar.lc=tmp			// initialize lc for small count
 (p6)	br.cond.dptk.few long_do_clear
 	;;				// WAR on ar.lc
 	//
@@ -91,7 +76,7 @@
 	// the various counters compared to how long the loop is supposed
 	// to last on average does not make this solution viable.
 	//
-1:	
+1:
 	EX( .Lexit1, st1 [buf]=r0,1 )
 	adds len=-1,len			// countdown length using len
 	br.cloop.dptk.few 1b
@@ -99,7 +84,7 @@
 	//
 	// .Lexit4: comes from byte by byte loop
 	//	    len contains bytes left
-.Lexit1:			
+.Lexit1:
 	mov ret0=len			// faster than using ar.lc
 	mov ar.lc=saved_lc
 	br.ret.sptk.few rp		// end of short clear_user
@@ -110,7 +95,7 @@
 	// so we focus on alignment (no branches required)
 	//
 	// The use of len/len2 for countdown of the number of bytes left
-	// instead of ret0 is due to the fact that the exception code 
+	// instead of ret0 is due to the fact that the exception code
 	// changes the values of r8.
 	//
 long_do_clear:
@@ -131,10 +116,10 @@
 	EX( .Lexit3, (p6) st8 [buf]=r0,8 )	// 8-byte aligned
 (p6)	adds len=-8,len;;
 	shr.u cnt=len,4		// number of 128-bit (2x64bit) words
-	;;	
+	;;
 	cmp.eq p6,p0=r0,cnt
 	adds tmp=-1,cnt
-(p6)	br.cond.dpnt.few .dotail 	// we have less than 16 bytes left
+(p6)	br.cond.dpnt.few .dotail	// we have less than 16 bytes left
 	;;
 	adds buf2=8,buf			// setup second base pointer
 	mov ar.lc=tmp
@@ -143,32 +128,30 @@
 	//
 	// 16bytes/iteration core loop
 	//
-	// The second store can never generate a fault because 
+	// The second store can never generate a fault because
 	// we come into the loop only when we are 16-byte aligned.
 	// This means that if we cross a page then it will always be
 	// in the first store and never in the second.
 	//
-	// 
+	//
 	// We need to keep track of the remaining length. A possible (optimistic)
-	// way would be to ue ar.lc and derive how many byte were left by
+	// way would be to use ar.lc and derive how many byte were left by
 	// doing : left= 16*ar.lc + 16.  this would avoid the addition at
-	// every iteration. 
+	// every iteration.
 	// However we need to keep the synchronization point. A template
 	// M;;MB does not exist and thus we can keep the addition at no
 	// extra cycle cost (use a nop slot anyway). It also simplifies the
 	// (unlikely)  error recovery code
 	//
 
-2:					
-
-	EX(.Lexit3, st8 [buf]=r0,16 )
+2:	EX(.Lexit3, st8 [buf]=r0,16 )
 	;;				// needed to get len correct when error
 	st8 [buf2]=r0,16
-	adds len=-16,len		
+	adds len=-16,len
 	br.cloop.dptk.few 2b
 	;;
 	mov ar.lc=saved_lc
-	// 
+	//
 	// tail correction based on len only
 	//
 	// We alternate the use of len3,len2 to allow parallelism and correct
@@ -176,14 +159,14 @@
 	// The addition of len2/len3 does not cost anything more compared to
 	// the regular memset as we had empty slots.
 	//
-.dotail:				
+.dotail:
 	mov len2=len			// for parallelization of error handling
 	mov len3=len
-	tbit.nz p6,p0=len,3	
+	tbit.nz p6,p0=len,3
 	;;
 	EX( .Lexit2, (p6) st8 [buf]=r0,8 )	// at least 8 bytes
 (p6)	adds len3=-8,len2
-	tbit.nz p7,p6=len,2	
+	tbit.nz p7,p6=len,2
 	;;
 	EX( .Lexit2, (p7) st4 [buf]=r0,4 )	// at least 4 bytes
 (p7)	adds len2=-4,len3
@@ -207,8 +190,8 @@
 	//
 	//
 	// .Lexit2:
-	// 	if p6 -> coming from st8 or st2 : len2 contains what's left
-	// 	if p7 -> coming from st4 or st1 : len3 contains what's left
+	//	if p6 -> coming from st8 or st2 : len2 contains what's left
+	//	if p7 -> coming from st4 or st1 : len3 contains what's left
 	// We must restore lc/pr even though might not have been used.
 .Lexit2:
 	.pred.rel "mutex", p6, p7
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/copy_page.S linux/arch/ia64/lib/copy_page.S
--- v2.4.3/linux/arch/ia64/lib/copy_page.S	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/lib/copy_page.S	Thu Apr  5 12:51:47 2001
@@ -3,14 +3,14 @@
  * Optimized version of the standard copy_page() function
  *
  * Based on comments from ddd. Try not to overflow write buffer.
- * 
+ *
  * Inputs:
- * 	in0:	address of target page
+ *	in0:	address of target page
  *	in1:	address of source page
  * Output:
- * 	no return value
+ *	no return value
  *
- * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999, 2001 Hewlett-Packard Co
  * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
  */
 #include <asm/asmmacro.h>
@@ -28,28 +28,23 @@
 #define tgt1		r22
 #define tgt2		r23
 
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 GLOBAL_ENTRY(copy_page)
-	UNW(.prologue)
-	UNW(.save ar.pfs, saved_pfs)
+	.prologue
+	.save ar.pfs, saved_pfs
 	alloc saved_pfs=ar.pfs,3,((2*PIPE_DEPTH+7)&~7),0,((2*PIPE_DEPTH+7)&~7)
 
 	.rotr t1[PIPE_DEPTH], t2[PIPE_DEPTH]
 	.rotp p[PIPE_DEPTH]
 
-	UNW(.save ar.lc, saved_lc)
+	.save ar.lc, saved_lc
 	mov saved_lc=ar.lc	// save ar.lc ahead of time
-	UNW(.save pr, saved_pr)
+	.save pr, saved_pr
 	mov saved_pr=pr		// rotating predicates are preserved
 				// resgisters we must save.
-	UNW(.body)
+	.body
 
-	mov src1=in1		// initialize 1st stream source 
-	adds src2=8,in1		// initialize 2nd stream source 
+	mov src1=in1		// initialize 1st stream source
+	adds src2=8,in1		// initialize 2nd stream source
 	mov lcount=PAGE_SIZE/16-1 // as many 16bytes as there are on a page
 				  // -1 is because br.ctop is repeat/until
 
@@ -72,7 +67,7 @@
 	//
 	// The initialization of the prolog is done via the predicate registers:
 	// the choice of EPI DEPENDS on the depth of the pipeline (n).
-	// When lc > 0 pr63=1 and it is fed back into pr16 and pr16-pr62 
+	// When lc > 0 pr63=1 and it is fed back into pr16 and pr16-pr62
 	// are then shifted right at every iteration,
 	// Thus by initializing pr16=1 and the rest to 0 before the loop
 	// we get EPI=1 after n iterations.
@@ -87,7 +82,7 @@
 				// stores but no loads anymore
 	;;
 	mov pr=saved_pr,0xffffffffffff0000	// restore predicates
-	mov ar.pfs=saved_pfs	// restore ar.ec 
+	mov ar.pfs=saved_pfs	// restore ar.ec
 	mov ar.lc=saved_lc	// restore saved lc
 	br.ret.sptk.few rp	// bye...
 END(copy_page)
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/copy_user.S linux/arch/ia64/lib/copy_user.S
--- v2.4.3/linux/arch/ia64/lib/copy_user.S	Tue Mar  6 19:44:35 2001
+++ linux/arch/ia64/lib/copy_user.S	Thu Apr  5 12:51:47 2001
@@ -12,41 +12,25 @@
  *
  * Inputs:
  *	in0	address of source buffer
- * 	in1	address of destination buffer
+ *	in1	address of destination buffer
  *	in2	number of bytes to copy
  *
- * Outputs: 
- * 	ret0	0 in case of success. The number of bytes NOT copied in
- * 		case of error.
+ * Outputs:
+ *	ret0	0 in case of success. The number of bytes NOT copied in
+ *		case of error.
  *
  * Copyright (C) 2000 Hewlett-Packard Co
  * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
  *
  * Fixme:
  *	- handle the case where we have more than 16 bytes and the alignment
- * 	  are different.
+ *	  are different.
  *	- more benchmarking
- * 	- fix extraneous stop bit introduced by the EX() macro.
+ *	- fix extraneous stop bit introduced by the EX() macro.
  */
 
 #include <asm/asmmacro.h>
 
-// The label comes first because our store instruction contains a comma
-// and confuse the preprocessor otherwise
-//
-#undef DEBUG
-#ifdef DEBUG
-#define EX(y,x...)				\
-99:	x
-#else
-#define EX(y,x...)				\
-	.section __ex_table,"a";		\
-	data4 @gprel(99f);			\
-	data4 y-99f;				\
-	.previous;				\
-99:	x
-#endif
-
 //
 // Tuneable parameters
 //
@@ -85,13 +69,10 @@
 #define enddst		r29
 #define endsrc		r30
 #define saved_pfs	r31
- 	.text
- 	.psr	abi64
- 	.psr	lsb
 
 GLOBAL_ENTRY(__copy_user)
-	UNW(.prologue)
-	UNW(.save ar.pfs, saved_pfs)
+	.prologue
+	.save ar.pfs, saved_pfs
 	alloc saved_pfs=ar.pfs,3,((2*PIPE_DEPTH+7)&~7),0,((2*PIPE_DEPTH+7)&~7)
 
 	.rotr val1[PIPE_DEPTH],val2[PIPE_DEPTH]
@@ -102,16 +83,16 @@
 
 	;;			// RAW of cfm when len=0
 	cmp.eq p8,p0=r0,len	// check for zero length
-	UNW(.save ar.lc, saved_lc)
+	.save ar.lc, saved_lc
 	mov saved_lc=ar.lc	// preserve ar.lc (slow)
 (p8)	br.ret.spnt.few rp	// empty mempcy()
 	;;
 	add enddst=dst,len	// first byte after end of source
 	add endsrc=src,len	// first byte after end of destination
-	UNW(.save pr, saved_pr)
+	.save pr, saved_pr
 	mov saved_pr=pr		// preserve predicates
 
-	UNW(.body)
+	.body
 
 	mov dst1=dst		// copy because of rotation
 	mov ar.ec=PIPE_DEPTH
@@ -119,7 +100,7 @@
 
 	mov src1=src		// copy because of rotation
 	mov ar.lc=len2		// initialize lc for small count
-	cmp.lt p10,p7=COPY_BREAK,len	// if len > COPY_BREAK then long copy 
+	cmp.lt p10,p7=COPY_BREAK,len	// if len > COPY_BREAK then long copy
 
 	xor tmp=src,dst		// same alignment test prepare
 (p10)	br.cond.dptk.few long_copy_user
@@ -128,9 +109,8 @@
 	// Now we do the byte by byte loop with software pipeline
 	//
 	// p7 is necessarily false by now
-1:				
+1:
 	EX(failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
-
 	EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
 	br.ctop.dptk.few 1b
 	;;
@@ -148,10 +128,10 @@
 	and src2=0x7,src1				// src offset
 	and dst2=0x7,dst1				// dst offset
 	;;
-	// The basic idea is that we copy byte-by-byte at the head so 
-	// that we can reach 8-byte alignment for both src1 and dst1. 
-	// Then copy the body using software pipelined 8-byte copy, 
-	// shifting the two back-to-back words right and left, then copy 
+	// The basic idea is that we copy byte-by-byte at the head so
+	// that we can reach 8-byte alignment for both src1 and dst1.
+	// Then copy the body using software pipelined 8-byte copy,
+	// shifting the two back-to-back words right and left, then copy
 	// the tail by copying byte-by-byte.
 	//
 	// Fault handling. If the byte-by-byte at the head fails on the
@@ -162,18 +142,18 @@
 	// handled simply by failure_in_pipe1.
 	//
 	// The case p14 represents the source has more bytes in the
-	// the first word (by the shifted part), whereas the p15 needs to 
-	// copy some bytes from the 2nd word of the source that has the 
+	// the first word (by the shifted part), whereas the p15 needs to
+	// copy some bytes from the 2nd word of the source that has the
 	// tail of the 1st of the destination.
 	//
 
 	//
-	// Optimization. If dst1 is 8-byte aligned (not rarely), we don't need 
-	// to copy the head to dst1, to start 8-byte copy software pipleline. 
+	// Optimization. If dst1 is 8-byte aligned (not rarely), we don't need
+	// to copy the head to dst1, to start 8-byte copy software pipleline.
 	// We know src1 is not 8-byte aligned in this case.
 	//
 	cmp.eq p14,p15=r0,dst2
-(p15)	br.cond.spnt.few 1f				
+(p15)	br.cond.spnt.few 1f
 	;;
 	sub t1=8,src2
 	mov t2=src2
@@ -182,10 +162,10 @@
 	sub len1=len,t1					// set len1
 	;;
 	sub lshift=64,rshift
-	;; 
+	;;
 	br.cond.spnt.few word_copy_user
-	;; 
-1:			
+	;;
+1:
 	cmp.leu	p14,p15=src2,dst2
 	sub t1=dst2,src2
 	;;
@@ -196,30 +176,29 @@
 	;;
 	// For the case p14, we don't need to copy the shifted part to
 	// the 1st word of destination.
-	sub t2=8,t1	
+	sub t2=8,t1
 (p14)	sub word1=word1,t1
 	;;
 	sub len1=len,word1				// resulting len
 (p15)	shl rshift=t1,3					// in bits
 (p14)	shl rshift=t2,3
-	;; 
+	;;
 (p14)	sub len1=len1,t1
 	adds cnt=-1,word1
-	;; 
+	;;
 	sub lshift=64,rshift
 	mov ar.ec=PIPE_DEPTH
 	mov pr.rot=1<<16	// p16=true all others are false
 	mov ar.lc=cnt
-	;; 
-2:	
+	;;
+2:
 	EX(failure_in_pipe2,(p16) ld1 val1[0]=[src1],1)
-	;; 
 	EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
 	br.ctop.dptk.few 2b
 	;;
-	clrrrb	
-	;; 
-word_copy_user:		
+	clrrrb
+	;;
+word_copy_user:
 	cmp.gtu p9,p0=16,len1
 (p9)	br.cond.spnt.few 4f		// if (16 > len1) skip 8-byte copy
 	;;
@@ -227,7 +206,7 @@
 	;;
 	adds cnt=-1,cnt
 	;;
-	.pred.rel "mutex", p14, p15	
+	.pred.rel "mutex", p14, p15
 (p14)	sub src1=src1,t2
 (p15)	sub src1=src1,t1
 	//
@@ -237,23 +216,23 @@
 	mov ar.lc=cnt
 	mov ar.ec=PIPE_DEPTH
 	mov pr.rot=1<<16	// p16=true all others are false
-	;; 
+	;;
 3:
 	//
-	// The pipleline consists of 3 stages:	
+	// The pipleline consists of 3 stages:
 	// 1 (p16):	Load a word from src1
 	// 2 (EPI_1):	Shift right pair, saving to tmp
 	// 3 (EPI):	Store tmp to dst1
 	//
-	// To make it simple, use at least 2 (p16) loops to set up val1[n] 
+	// To make it simple, use at least 2 (p16) loops to set up val1[n]
 	// because we need 2 back-to-back val1[] to get tmp.
 	// Note that this implies EPI_2 must be p18 or greater.
-	// 
+	//
 
 #define EPI_1		p[PIPE_DEPTH-2]
 #define SWITCH(pred, shift)	cmp.eq pred,p0=shift,rshift
 #define CASE(pred, shift)	\
-	(pred)	br.cond.spnt.few copy_user_bit##shift	
+	(pred)	br.cond.spnt.few copy_user_bit##shift
 #define BODY(rshift)							\
 copy_user_bit##rshift:							\
 1:									\
@@ -267,11 +246,11 @@
 	//
 	// Since the instruction 'shrp' requires a fixed 128-bit value
 	// specifying the bits to shift, we need to provide 7 cases
-	// below. 
+	// below.
 	//
 	SWITCH(p6, 8)
 	SWITCH(p7, 16)
-	SWITCH(p8, 24)	
+	SWITCH(p8, 24)
 	SWITCH(p9, 32)
 	SWITCH(p10, 40)
 	SWITCH(p11, 48)
@@ -289,40 +268,40 @@
 	BODY(16)
 	BODY(24)
 	BODY(32)
-	BODY(40)		
+	BODY(40)
 	BODY(48)
 	BODY(56)
-	;; 
-.diff_align_do_tail:	
-	.pred.rel "mutex", p14, p15		
+	;;
+.diff_align_do_tail:
+	.pred.rel "mutex", p14, p15
 (p14)	sub src1=src1,t1
-(p14)	adds dst1=-8,dst1			
+(p14)	adds dst1=-8,dst1
 (p15)	sub dst1=dst1,t1
-	;; 
-4:	
+	;;
+4:
 	// Tail correction.
 	//
 	// The problem with this piplelined loop is that the last word is not
-	// loaded and thus parf of the last word written is not correct. 
+	// loaded and thus parf of the last word written is not correct.
 	// To fix that, we simply copy the tail byte by byte.
-	
+
 	sub len1=endsrc,src1,1
 	clrrrb
-	;; 
+	;;
 	mov ar.ec=PIPE_DEPTH
 	mov pr.rot=1<<16	// p16=true all others are false
 	mov ar.lc=len1
 	;;
-5:		
+5:
 	EX(failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
-	
 	EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
 	br.ctop.dptk.few 5b
 	;;
+	mov ar.lc=saved_lc
 	mov pr=saved_pr,0xffffffffffff0000
 	mov ar.pfs=saved_pfs
 	br.ret.dptk.few rp
-	
+
 	//
 	// Beginning of long mempcy (i.e. > 16 bytes)
 	//
@@ -353,6 +332,7 @@
 	// we have never executed the ld1, therefore st1 is not executed.
 	//
 	EX(failure_in1,(p8) ld4 val2[0]=[src1],4)	// 4-byte aligned
+	;;
 	EX(failure_out,(p6) st1 [dst1]=val1[0],1)
 	tbit.nz p9,p0=src1,3
 	;;
@@ -369,12 +349,12 @@
 	shr.u cnt=len1,4		// number of 128-bit (2x64bit) words
 	;;
 	EX(failure_out, (p9) st8 [dst1]=val2[1],8)
-	tbit.nz p6,p0=len1,3	
+	tbit.nz p6,p0=len1,3
 	cmp.eq p7,p0=r0,cnt
 	adds tmp=-1,cnt			// br.ctop is repeat/until
 (p7)	br.cond.dpnt.few .dotail	// we have less than 16 bytes left
 	;;
-	adds src2=8,src1	
+	adds src2=8,src1
 	adds dst2=8,dst1
 	mov ar.lc=tmp
 	;;
@@ -395,12 +375,12 @@
 	// No matter where we come from (loop or test) the src1 pointer
 	// is 16 byte aligned AND we have less than 16 bytes to copy.
 	//
-.dotail:			
+.dotail:
 	EX(failure_in1,(p6) ld8 val1[0]=[src1],8)	// at least 8 bytes
 	tbit.nz p7,p0=len1,2
 	;;
 	EX(failure_in1,(p7) ld4 val1[1]=[src1],4)	// at least 4 bytes
- 	tbit.nz p8,p0=len1,1
+	tbit.nz p8,p0=len1,1
 	;;
 	EX(failure_in1,(p8) ld2 val2[0]=[src1],2)	// at least 2 bytes
 	tbit.nz p9,p0=len1,0
@@ -430,7 +410,7 @@
 	//
 	//	  In the same loop iteration, the dst1 pointer does not directly
 	//	  reflect where the faulty load was.
-	//	  
+	//
 	//	- pipeline effect
 	//	  When you get a fault on load, you may have valid data from
 	//	  previous loads not yet store in transit. Such data must be
@@ -442,7 +422,7 @@
 	//	- we don't disrupt the pipeline, i.e. data in transit in
 	//	  the software pipeline will be eventually move to memory.
 	//	  We simply replace the load with a simple mov and keep the
-	//	  pipeline going. We can't really do this inline because 
+	//	  pipeline going. We can't really do this inline because
 	//	  p16 is always reset to 1 when lc > 0.
 	//
 failure_in_pipe1:
@@ -459,7 +439,7 @@
 
 	//
 	// This is the case where the byte by byte copy fails on the load
-	// when we copy the head. We need to finish the pipeline and copy 
+	// when we copy the head. We need to finish the pipeline and copy
 	// zeros for the rest of the destination. Since this happens
 	// at the top we still need to fill the body and tail.
 failure_in_pipe2:
@@ -471,7 +451,7 @@
 	;;
 	sub len=enddst,dst1,1		// precompute len
 	br.cond.dptk.few failure_in1bis
-	;; 
+	;;
 
 	//
 	// Here we handle the head & tail part when we check for alignment.
@@ -482,7 +462,7 @@
 	//
 	// However some simplifications are possible given the way
 	// things work.
-	// 
+	//
 	// 1) HEAD
 	// Theory of operation:
 	//
@@ -506,23 +486,23 @@
 	//
 	// Key point:
 	//	- if you fail on 1, 2, 4 then you have never executed any smaller
-	//	  size loads, e.g. failing ld4 means no ld1 nor ld2 executed 
+	//	  size loads, e.g. failing ld4 means no ld1 nor ld2 executed
 	//	  before.
 	//
 	// This allows us to simplify the cleanup code, because basically you
 	// only have to worry about "pending" stores in the case of a failing
-	// ld8(). Given the way the code is written today, this means only 
+	// ld8(). Given the way the code is written today, this means only
 	// worry about st2, st4. There we can use the information encapsulated
 	// into the predicates.
-	// 
+	//
 	// Other key point:
-	// 	- if you fail on the ld8 in the head, it means you went straight
+	//	- if you fail on the ld8 in the head, it means you went straight
 	//	  to it, i.e. 8byte alignment within an unexisting page.
 	// Again this comes from the fact that if you crossed just for the ld8 then
 	// you are 8byte aligned but also 16byte align, therefore you would
 	// either go for the 16byte copy loop OR the ld8 in the tail part.
 	// The combination ld1, ld2, ld4, ld8 where you fail on ld8 is impossible
-	// because it would mean you had 15bytes to copy in which case you 
+	// because it would mean you had 15bytes to copy in which case you
 	// would have defaulted to the byte by byte copy.
 	//
 	//
@@ -533,18 +513,18 @@
 	// Key point:
 	// This means that we either:
 	//		- are right on a page boundary
-	//	OR 
-	//		- are at more than 16 bytes from a page boundary with 
+	//	OR
+	//		- are at more than 16 bytes from a page boundary with
 	//		  at most 15 bytes to copy: no chance of crossing.
 	//
 	// This allows us to assume that if we fail on a load we haven't possibly
-	// executed any of the previous (tail) ones, so we don't need to do 
-	// any stores. For instance, if we fail on ld2, this means we had 
+	// executed any of the previous (tail) ones, so we don't need to do
+	// any stores. For instance, if we fail on ld2, this means we had
 	// 2 or 3 bytes left to copy and we did not execute the ld8 nor ld4.
 	//
-	// This means that we are in a situation similar the a fault in the 
-	// head part. That's nice! 
-	// 
+	// This means that we are in a situation similar the a fault in the
+	// head part. That's nice!
+	//
 failure_in1:
 //	sub ret0=enddst,dst1	// number of bytes to zero, i.e. not copied
 //	sub len=enddst,dst1,1
@@ -563,7 +543,7 @@
 	;;
 5:
 	st1 [dst1]=r0,1
-	br.cloop.dptk.few 5b	
+	br.cloop.dptk.few 5b
 	;;
 skip_loop:
 	mov pr=saved_pr,0xffffffffffff0000
@@ -574,7 +554,7 @@
 	//
 	// Here we simply restart the loop but instead
 	// of doing loads we fill the pipeline with zeroes
-	// We can't simply store r0 because we may have valid 
+	// We can't simply store r0 because we may have valid
 	// data in transit in the pipeline.
 	// ar.lc and ar.ec are setup correctly at this point
 	//
@@ -593,7 +573,7 @@
 	;;
 	cmp.ne p6,p0=dst1,enddst	// Do we need to finish the tail ?
 	sub len=enddst,dst1,1		// precompute len
-(p6)	br.cond.dptk.few failure_in1bis	
+(p6)	br.cond.dptk.few failure_in1bis
 	;;
 	mov pr=saved_pr,0xffffffffffff0000
 	mov ar.lc=saved_lc
@@ -610,13 +590,13 @@
 	;;
 	cmp.ne p6,p0=dst1,enddst	// Do we need to finish the tail ?
 	sub len=enddst,dst1,1		// precompute len
-(p6)	br.cond.dptk.few failure_in1bis	
+(p6)	br.cond.dptk.few failure_in1bis
 	;;
 	mov pr=saved_pr,0xffffffffffff0000
 	mov ar.lc=saved_lc
 	mov ar.pfs=saved_pfs
 	br.ret.dptk.few rp
-	
+
 	//
 	// handling of failures on stores: that's the easy part
 	//
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/csum_partial_copy.c linux/arch/ia64/lib/csum_partial_copy.c
--- v2.4.3/linux/arch/ia64/lib/csum_partial_copy.c	Sun Feb  6 18:42:40 2000
+++ linux/arch/ia64/lib/csum_partial_copy.c	Thu Apr  5 12:51:47 2001
@@ -1,6 +1,6 @@
 /*
  * Network Checksum & Copy routine
- * 
+ *
  * Copyright (C) 1999 Hewlett-Packard Co
  * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
  *
@@ -107,22 +107,18 @@
 do_csum_partial_copy_from_user (const char *src, char *dst, int len,
 				unsigned int psum, int *errp)
 {
-	const unsigned char *psrc = src;
 	unsigned long result;
-	int cplen = len;
-	int r = 0;
 
 	/* XXX Fixme
-	 * for now we separate the copy from checksum for obvious 
+	 * for now we separate the copy from checksum for obvious
 	 * alignment difficulties. Look at the Alpha code and you'll be
 	 * scared.
 	 */
 
-	while ( cplen-- ) r |=__get_user(*dst++,psrc++);
-
-	if ( r && errp ) *errp = r;
+	if (__copy_from_user(dst, src, len) != 0 && errp)
+		*errp = -EFAULT;
 
-	result = do_csum(src, len);
+	result = do_csum(dst, len);
 
 	/* add in old sum, and carry.. */
 	result += psum;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/do_csum.S linux/arch/ia64/lib/do_csum.S
--- v2.4.3/linux/arch/ia64/lib/do_csum.S	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/lib/do_csum.S	Thu Apr  5 12:51:47 2001
@@ -7,8 +7,8 @@
  * Inputs:
  *	in0: address of buffer to checksum (char *)
  *	in1: length of the buffer (int)
- * 
- * Copyright (C) 1999 Hewlett-Packard Co
+ *
+ * Copyright (C) 1999, 2001 Hewlett-Packard Co
  * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
  *
  */
@@ -39,7 +39,7 @@
 //	This version avoids synchronization in the core loop by also using a
 //	pipeline for the accumulation of the checksum in result[].
 //
-//	 p[]     
+//	 p[]
 //	|---|
 //     0|   | r32 : new value loaded in pipeline
 //	|---|
@@ -50,7 +50,7 @@
 //     3|   | r35 : previous value added to checksum (previous iteration)
 //      |---|
 //
-//	result[] 
+//	result[]
 //	|---|
 //     0|   | r36 : new checksum
 //	|---|
@@ -68,7 +68,7 @@
 //	- Maybe another algorithm which would take care of the folding at the
 //	  end in a different manner
 //	- Work with people more knowledgeable than me on the network stack
-//	  to figure out if we could not split the function depending on the 
+//	  to figure out if we could not split the function depending on the
 //	  type of packet or alignment we get. Like the ip_fast_csum() routine
 //	  where we know we have at least 20bytes worth of data to checksum.
 //	- Look at RFCs about checksums to see whether or not we can do better
@@ -94,17 +94,11 @@
 #define buf		in0
 #define len		in1
 
-
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 // unsigned long do_csum(unsigned char *buf,int len)
 
 GLOBAL_ENTRY(do_csum)
-	UNW(.prologue)
-	UNW(.save ar.pfs, saved_pfs)
+	.prologue
+	.save ar.pfs, saved_pfs
 	alloc saved_pfs=ar.pfs,2,8,0,8
 
 	.rotr p[4], result[3]
@@ -126,7 +120,7 @@
 	;;
 	and lastoff=7,tmp1	// how many bytes off for last element
 	andcm last=tmp2,tmp3	// address of word containing last byte
-	UNW(.save pr, saved_pr)
+	.save pr, saved_pr
 	mov saved_pr=pr		// preserve predicates (rotation)
 	;;
 	sub tmp3=last,first	// tmp3=distance from first to last
@@ -144,14 +138,14 @@
 	;;
 
 	shl tmp1=tmp1,3		// number of bits
-	shl hmask=hmask,tmp2 	// build head mask, mask off [0,firstoff[
+	shl hmask=hmask,tmp2	// build head mask, mask off [0,firstoff[
 	;;
 	shr.u tmask=tmask,tmp1	// build tail mask, mask off ]8,lastoff]
-	UNW(.save ar.lc, saved_lc)
+	.save ar.lc, saved_lc
 	mov saved_lc=ar.lc	// save lc
 	;;
 
-	UNW(.body)
+	.body
 
 (p8)	and hmask=hmask,tmask	// apply tail mask to head mask if 1 word only
 (p9)	and p[1]=lastval,tmask	// mask last it as appropriate
@@ -163,7 +157,7 @@
 	;;
 	// XXX Fixme: not very nice initialization here
 	//
-	// Setup loop control registers: 
+	// Setup loop control registers:
 	//
 	// tmp3=0 (1 word)   : lc=0, ec=2, p16=F
 	// tmp3=1 (2 words)  : lc=0, ec=3, p16=F
@@ -227,7 +221,7 @@
 	add ret0=tmp1,tmp2
 	mov pr=saved_pr,0xffffffffffff0000
 	;;
-	// if buf was odd then swap bytes 
+	// if buf was odd then swap bytes
 	mov ar.pfs=saved_pfs		// restore ar.ec
 (p10)	mux1 ret0=ret0,@rev		// reverse word
 	;;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/flush.S linux/arch/ia64/lib/flush.S
--- v2.4.3/linux/arch/ia64/lib/flush.S	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/lib/flush.S	Thu Apr  5 12:51:47 2001
@@ -1,30 +1,25 @@
 /*
  * Cache flushing routines.
  *
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #include <asm/asmmacro.h>
 #include <asm/page.h>
 
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 	/*
 	 * flush_icache_range(start,end)
 	 *	Must flush range from start to end-1 but nothing else (need to
 	 *	be careful not to touch addresses that may be unmapped).
 	 */
 GLOBAL_ENTRY(flush_icache_range)
-	UNW(.prologue)
+	.prologue
 	alloc r2=ar.pfs,2,0,0,0
 	sub r8=in1,in0,1
 	;;
 	shr.u r8=r8,5			// we flush 32 bytes per iteration
-	UNW(.save ar.lc, r3)
-	mov r3=ar.lc			// save ar.lc	
+	.save ar.lc, r3
+	mov r3=ar.lc			// save ar.lc
 	;;
 
 	.body
@@ -38,7 +33,7 @@
 	sync.i
 	;;
 	srlz.i
-	;;	
+	;;
 	mov ar.lc=r3			// restore ar.lc
 	br.ret.sptk.many rp
 END(flush_icache_range)
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/idiv64.S linux/arch/ia64/lib/idiv64.S
--- v2.4.3/linux/arch/ia64/lib/idiv64.S	Mon Oct  9 17:54:56 2000
+++ linux/arch/ia64/lib/idiv64.S	Thu Apr  5 12:51:47 2001
@@ -37,28 +37,29 @@
 #define NAME		PASTE(PASTE(__,SGN),PASTE(OP,di3))
 
 GLOBAL_ENTRY(NAME)
-	UNW(.prologue)
+	.prologue
 	.regstk 2,0,0,0
 	// Transfer inputs to FP registers.
 	setf.sig f8 = in0
 	setf.sig f9 = in1
-	UNW(.fframe 16)
-	UNW(.save.f 0x20)
+	;;
+	.fframe 16
+	.save.f 0x20
 	stf.spill [sp] = f17,-16
 
 	// Convert the inputs to FP, to avoid FP software-assist faults.
 	INT_TO_FP(f8, f8)
 	;;
 
-	UNW(.save.f 0x10)
+	.save.f 0x10
 	stf.spill [sp] = f16
-	UNW(.body)
+	.body
 	INT_TO_FP(f9, f9)
 	;;
 	frcpa.s1 f17, p6 = f8, f9	// y0 = frcpa(b)
 	;;
 (p6)	fmpy.s1 f7 = f8, f17		// q0 = a*y0
-(p6)	fnma.s1 f6 = f9, f17, f1	// e0 = -b*y0 + 1 
+(p6)	fnma.s1 f6 = f9, f17, f1	// e0 = -b*y0 + 1
 	;;
 (p6)	fma.s1 f16 = f7, f6, f7		// q1 = q0*e0 + q0
 (p6)	fmpy.s1 f7 = f6, f6		// e1 = e0*e0
@@ -70,7 +71,7 @@
 (p6)	fma.s1 f6 = f17, f6, f17	// y1 = y0*e0 + y0
 	;;
 (p6)	fma.s1 f6 = f6, f7, f6		// y2 = y1*e1 + y1
-(p6)	fnma.s1 f7 = f9, f16, f8	// r = -b*q2 + a 
+(p6)	fnma.s1 f7 = f9, f16, f8	// r = -b*q2 + a
 	;;
 #ifdef MODULO
 	setf.sig f8 = in0		// f8 = a
@@ -78,7 +79,7 @@
 #endif
 (p6)	fma.s1 f17 = f7, f6, f16	// q3 = r*y2 + q2
 	;;
-	UNW(.restore sp)
+	.restore sp
 	ldf.fill f16 = [sp], 16
 	FP_TO_INT(f17, f17)		// q = trunc(q3)
 	;;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/memcpy.S linux/arch/ia64/lib/memcpy.S
--- v2.4.3/linux/arch/ia64/lib/memcpy.S	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/lib/memcpy.S	Thu Apr  5 12:51:47 2001
@@ -68,19 +68,19 @@
 	 * the more general copy routine handling arbitrary
 	 * sizes/alignment etc.
 	 */
-	UNW(.prologue)
-	UNW(.save ar.pfs, saved_pfs)
+	.prologue
+	.save ar.pfs, saved_pfs
 	alloc saved_pfs=ar.pfs,3,Nrot,0,Nrot
-	UNW(.save ar.lc, saved_lc)
+	.save ar.lc, saved_lc
 	mov saved_lc=ar.lc
 	or t0=in0,in1
 	;;
 
 	or t0=t0,in2
-	UNW(.save pr, saved_pr)
+	.save pr, saved_pr
 	mov saved_pr=pr
 
-	UNW(.body)
+	.body
 
 	cmp.eq p6,p0=in2,r0	// zero length?
 	mov retval=in0		// return dst
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/memset.S linux/arch/ia64/lib/memset.S
--- v2.4.3/linux/arch/ia64/lib/memset.S	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/lib/memset.S	Thu Apr  5 12:51:47 2001
@@ -3,14 +3,13 @@
  * Optimized version of the standard memset() function
  *
  * Return: none
- *         
  *
  * Inputs:
  *	in0:	address of buffer
  * 	in1:	byte value to use for storing
  *	in2:	length of the buffer
  *
- * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999, 2001 Hewlett-Packard Co
  * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
  */
 
@@ -31,20 +30,16 @@
 #define saved_lc	r20
 #define tmp		r21
 
- 	.text
- 	.psr	abi64
- 	.psr	lsb
-
 GLOBAL_ENTRY(memset)
-	UNW(.prologue)
-	UNW(.save ar.pfs, saved_pfs)
- 	alloc	saved_pfs=ar.pfs,3,0,0,0	// cnt is sink here
+	.prologue
+	.save ar.pfs, saved_pfs
+ 	alloc saved_pfs=ar.pfs,3,0,0,0	// cnt is sink here
 	cmp.eq p8,p0=r0,len	// check for zero length
-	UNW(.save ar.lc, saved_lc)
+	.save ar.lc, saved_lc
 	mov saved_lc=ar.lc	// preserve ar.lc (slow)
-	;; 
+	;;
 
-	UNW(.body)
+	.body
 
 	adds tmp=-1,len		// br.ctop is repeat/until
 	tbit.nz p6,p0=buf,0	// odd alignment
@@ -82,7 +77,7 @@
 (p6)	st8 [buf]=val,8		// 8-byte aligned
 (p6)	adds len=-8,len;;
 	shr.u cnt=len,4		// number of 128-bit (2x64bit) words
-	;;	
+	;;
 	cmp.eq p6,p0=r0,cnt
 	adds tmp=-1,cnt
 (p6)	br.cond.dpnt.few .dotail // we have less than 16 bytes left
@@ -96,10 +91,10 @@
 	br.cloop.dptk.few 2b
 	;;
 .dotail:			// tail correction based on len only
-	tbit.nz p6,p0=len,3	
+	tbit.nz p6,p0=len,3
 	;;
 (p6)	st8 [buf]=val,8		// at least 8 bytes
-	tbit.nz p6,p0=len,2	
+	tbit.nz p6,p0=len,2
 	;;
 (p6)	st4 [buf]=val,4		// at least 4 bytes
 	tbit.nz p6,p0=len,1
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/strlen.S linux/arch/ia64/lib/strlen.S
--- v2.4.3/linux/arch/ia64/lib/strlen.S	Tue Mar  6 19:44:35 2001
+++ linux/arch/ia64/lib/strlen.S	Thu Apr  5 12:51:47 2001
@@ -5,12 +5,12 @@
  *
  * Inputs:
  *	in0	address of string
- * 
- * Outputs: 
- * 	ret0	the number of characters in the string (0 if empty string)
- *         	does not count the \0
  *
- * Copyright (C) 1999 Hewlett-Packard Co
+ * Outputs:
+ *	ret0	the number of characters in the string (0 if empty string)
+ *	does not count the \0
+ *
+ * Copyright (C) 1999, 2001 Hewlett-Packard Co
  * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
  *
  * 09/24/99 S.Eranian add speculation recovery code
@@ -30,7 +30,7 @@
 //	  string may not be 8-byte aligned. In this case we load the 8byte
 //	  quantity which includes the start of the string and mask the unused
 //	  bytes with 0xff to avoid confusing czx.
-//	  We use speculative loads and software pipelining to hide memory 
+//	  We use speculative loads and software pipelining to hide memory
 //	  latency and do read ahead safely. This way we defer any exception.
 //
 //	  Because we don't want the kernel to be relying on particular
@@ -42,7 +42,7 @@
 //	  The fact that speculation may fail can be caused, for instance, by
 //	  the DCR.dm bit being set. In this case TLB misses are deferred, i.e.,
 //	  a NaT bit will be set if the translation is not present. The normal
-//	  load, on the other hand, will cause the translation to be inserted 
+//	  load, on the other hand, will cause the translation to be inserted
 //	  if the mapping exists.
 //
 //	  It should be noted that we execute recovery code only when we need
@@ -50,22 +50,22 @@
 //	  recovery code on pure read ahead data.
 //
 // Remarks:
-//	- the cmp r0,r0 is used as a fast way to initialize a predicate 
+//	- the cmp r0,r0 is used as a fast way to initialize a predicate
 //	  register to 1. This is required to make sure that we get the parallel
 //	  compare correct.
 //
 //	- we don't use the epilogue counter to exit the loop but we need to set
 //	  it to zero beforehand.
 //
-//	- after the loop we must test for Nat values because neither the 
+//	- after the loop we must test for Nat values because neither the
 //	  czx nor cmp instruction raise a NaT consumption fault. We must be
-//	  careful not to look too far for a Nat for which we don't care. 
+//	  careful not to look too far for a Nat for which we don't care.
 //	  For instance we don't need to look at a NaT in val2 if the zero byte
 //	  was in val1.
 //
 //	- Clearly performance tuning is required.
 //
-// 
+//
 //
 #define saved_pfs	r11
 #define	tmp		r10
@@ -78,15 +78,9 @@
 #define val1		r22
 #define val2		r23
 
-
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 GLOBAL_ENTRY(strlen)
-	UNW(.prologue)
-	UNW(.save ar.pfs, saved_pfs)
+	.prologue
+	.save ar.pfs, saved_pfs
 	alloc saved_pfs=ar.pfs,11,0,0,8 // rotating must be multiple of 8
 
 	.rotr v[2], w[2]	// declares our 4 aliases
@@ -94,11 +88,11 @@
 	extr.u tmp=in0,0,3	// tmp=least significant 3 bits
 	mov orig=in0		// keep trackof initial byte address
 	dep src=0,in0,0,3	// src=8byte-aligned in0 address
-	UNW(.save pr, saved_pr)
+	.save pr, saved_pr
 	mov saved_pr=pr		// preserve predicates (rotation)
 	;;
 
-	UNW(.body)
+	.body
 
 	ld8 v[1]=[src],8	// must not speculate: can fail here
 	shl tmp=tmp,3		// multiply by 8bits/byte
@@ -115,8 +109,8 @@
 	or v[1]=v[1],mask	// now we have a safe initial byte pattern
 	;;
 1:
-	ld8.s v[0]=[src],8	// speculatively load next 
-	czx1.r val1=v[1]	// search 0 byte from right 
+	ld8.s v[0]=[src],8	// speculatively load next
+	czx1.r val1=v[1]	// search 0 byte from right
 	czx1.r val2=w[1]	// search 0 byte from right following 8bytes
 	;;
 	ld8.s w[0]=[src],8	// speculatively load next to next
@@ -132,11 +126,7 @@
 	//	- there must be a better way of doing the test
 	//
 	cmp.eq  p8,p9=8,val1	// p6 = val1 had zero (disambiguate)
-#ifdef notyet
 	tnat.nz p6,p7=val1	// test NaT on val1
-#else
-	tnat.z p7,p6=val1	// test NaT on val1
-#endif
 (p6)	br.cond.spnt.few recover// jump to recovery if val1 is NaT
 	;;
 	//
@@ -154,7 +144,7 @@
 	sub tmp=8,val1		// which byte in word
 	mov pr=saved_pr,0xffffffffffff0000
 	;;
-	sub ret0=ret0,tmp	// adjust 
+	sub ret0=ret0,tmp	// adjust
 	mov ar.pfs=saved_pfs	// because of ar.ec, restore no matter what
 	br.ret.sptk.few rp	// end of normal execution
 
@@ -167,8 +157,8 @@
 	//
 	// IMPORTANT:
 	// Please note that in the case of strlen() as opposed to strlen_user()
-	// we don't use the exception mechanism, as this function is not 
-	// supposed to fail. If that happens it means we have a bug and the 
+	// we don't use the exception mechanism, as this function is not
+	// supposed to fail. If that happens it means we have a bug and the
 	// code will cause of kernel fault.
 	//
 	// XXX Fixme
@@ -187,7 +177,7 @@
 2:
 (p6)	ld8 val=[base],8	// will fail if unrecoverable fault
 	;;
-	czx1.r val1=val		// search 0 byte from right 
+	czx1.r val1=val		// search 0 byte from right
 	;;
 	cmp.eq p6,p0=8,val1	// val1==8 ?
 (p6)	br.wtop.dptk.few 2b	// loop until p6 == 0
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/strlen_user.S linux/arch/ia64/lib/strlen_user.S
--- v2.4.3/linux/arch/ia64/lib/strlen_user.S	Tue Mar  6 19:44:35 2001
+++ linux/arch/ia64/lib/strlen_user.S	Thu Apr  5 12:51:47 2001
@@ -6,9 +6,9 @@
  *
  * Outputs:
  *	ret0	0 in case of fault, strlen(buffer)+1 otherwise
- * 
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
  *
  * 01/19/99 S.Eranian heavily enhanced version (see details below)
@@ -24,8 +24,8 @@
 //	- length of string + 1
 //	- 0 in case an exception is raised
 //
-// This is an enhanced version of the basic strlen_user. it includes a 
-// combination of compute zero index (czx), parallel comparisons, speculative 
+// This is an enhanced version of the basic strlen_user. it includes a
+// combination of compute zero index (czx), parallel comparisons, speculative
 // loads and loop unroll using rotating registers.
 //
 // General Ideas about the algorithm:
@@ -34,7 +34,7 @@
 //	  string may not be 8-byte aligned. In this case we load the 8byte
 //	  quantity which includes the start of the string and mask the unused
 //	  bytes with 0xff to avoid confusing czx.
-//	  We use speculative loads and software pipelining to hide memory 
+//	  We use speculative loads and software pipelining to hide memory
 //	  latency and do read ahead safely. This way we defer any exception.
 //
 //	  Because we don't want the kernel to be relying on particular
@@ -45,7 +45,7 @@
 //	  The fact that speculation may fail can be caused, for instance, by
 //	  the DCR.dm bit being set. In this case TLB misses are deferred, i.e.,
 //	  a NaT bit will be set if the translation is not present. The normal
-//	  load, on the other hand, will cause the translation to be inserted 
+//	  load, on the other hand, will cause the translation to be inserted
 //	  if the mapping exists.
 //
 //	  It should be noted that we execute recovery code only when we need
@@ -53,30 +53,21 @@
 //	  recovery code on pure read ahead data.
 //
 // Remarks:
-//	- the cmp r0,r0 is used as a fast way to initialize a predicate 
+//	- the cmp r0,r0 is used as a fast way to initialize a predicate
 //	  register to 1. This is required to make sure that we get the parallel
 //	  compare correct.
 //
 //	- we don't use the epilogue counter to exit the loop but we need to set
 //	  it to zero beforehand.
 //
-//	- after the loop we must test for Nat values because neither the 
+//	- after the loop we must test for Nat values because neither the
 //	  czx nor cmp instruction raise a NaT consumption fault. We must be
-//	  careful not to look too far for a Nat for which we don't care. 
+//	  careful not to look too far for a Nat for which we don't care.
 //	  For instance we don't need to look at a NaT in val2 if the zero byte
 //	  was in val1.
 //
 //	- Clearly performance tuning is required.
 //
-// 
-//
-
-#define EX(y,x...)				\
-	.section __ex_table,"a";		\
-	data4 @gprel(99f);			\
-	data4 y-99f;				\
-	.previous;				\
-99:	x
 
 #define saved_pfs	r11
 #define	tmp		r10
@@ -89,15 +80,9 @@
 #define val1		r22
 #define val2		r23
 
-
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 GLOBAL_ENTRY(__strlen_user)
-	UNW(.prologue)
-	UNW(.save ar.pfs, saved_pfs)
+	.prologue
+	.save ar.pfs, saved_pfs
 	alloc saved_pfs=ar.pfs,11,0,0,8
 
 	.rotr v[2], w[2]	// declares our 4 aliases
@@ -105,7 +90,7 @@
 	extr.u tmp=in0,0,3	// tmp=least significant 3 bits
 	mov orig=in0		// keep trackof initial byte address
 	dep src=0,in0,0,3	// src=8byte-aligned in0 address
-	UNW(.save pr, saved_pr)
+	.save pr, saved_pr
 	mov saved_pr=pr		// preserve predicates (rotation)
 	;;
 
@@ -127,8 +112,8 @@
 	or v[1]=v[1],mask	// now we have a safe initial byte pattern
 	;;
 1:
-	ld8.s v[0]=[src],8	// speculatively load next 
-	czx1.r val1=v[1]	// search 0 byte from right 
+	ld8.s v[0]=[src],8	// speculatively load next
+	czx1.r val1=v[1]	// search 0 byte from right
 	czx1.r val2=w[1]	// search 0 byte from right following 8bytes
 	;;
 	ld8.s w[0]=[src],8	// speculatively load next to next
@@ -144,11 +129,7 @@
 	//	- there must be a better way of doing the test
 	//
 	cmp.eq  p8,p9=8,val1	// p6 = val1 had zero (disambiguate)
-#ifdef notyet
 	tnat.nz p6,p7=val1	// test NaT on val1
-#else
-	tnat.z p7,p6=val1	// test NaT on val1
-#endif
 (p6)	br.cond.spnt.few recover// jump to recovery if val1 is NaT
 	;;
 	//
@@ -193,7 +174,7 @@
 2:
 	EX(.Lexit1, (p6) ld8 val=[base],8)
 	;;
-	czx1.r val1=val		// search 0 byte from right 
+	czx1.r val1=val		// search 0 byte from right
 	;;
 	cmp.eq p6,p0=8,val1	// val1==8 ?
 (p6)	br.wtop.dptk.few 2b	// loop until p6 == 0
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/strncpy_from_user.S linux/arch/ia64/lib/strncpy_from_user.S
--- v2.4.3/linux/arch/ia64/lib/strncpy_from_user.S	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/lib/strncpy_from_user.S	Thu Apr  5 12:51:47 2001
@@ -8,9 +8,9 @@
  *	in2:	length of buffer in bytes
  * Outputs:
  *	r8:	-EFAULT in case of fault or number of bytes copied if no fault
- * 
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * 00/03/06 D. Mosberger Fixed to return proper return value (bug found by
  *			 by Andreas Schwab <schwab@suse.de>).
@@ -18,18 +18,6 @@
 
 #include <asm/asmmacro.h>
 
-#define EX(x...)				\
-99:	x;					\
-	.section __ex_table,"a";		\
-	data4 @gprel(99b);			\
-	data4 .Lexit-99b;			\
-	.previous
-
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 GLOBAL_ENTRY(__strncpy_from_user)
 	alloc r2=ar.pfs,3,0,0,0
 	mov r8=0
@@ -41,15 +29,16 @@
 
 	// XXX braindead copy loop---this needs to be optimized
 .Loop1:
-	EX(ld1 r8=[in1],1;; st1 [in0]=r8,1; cmp.ne p6,p7=r8,r0)
+	EX(.Lexit, ld1 r8=[in1],1)
+	;;
+	EX(.Lexit, st1 [in0]=r8,1)
+	cmp.ne p6,p7=r8,r0
 	;;
 (p6)	cmp.ne.unc p8,p0=in1,r10
 (p8)	br.cond.dpnt.few .Loop1
 	;;
 (p6)	mov r8=in2		// buffer filled up---return buffer length
 (p7)	sub r8=in1,r9,1		// return string length (excluding NUL character)
-	br.ret.sptk.few rp
-
-.Lexit:
+[.Lexit:]
 	br.ret.sptk.few rp
 END(__strncpy_from_user)
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/strnlen_user.S linux/arch/ia64/lib/strnlen_user.S
--- v2.4.3/linux/arch/ia64/lib/strnlen_user.S	Thu Jun 22 07:09:44 2000
+++ linux/arch/ia64/lib/strnlen_user.S	Thu Apr  5 12:51:47 2001
@@ -8,41 +8,28 @@
  *	in1:	string length limit N
  * Outputs:
  *	r8:	0 in case of fault, strlen(buffer)+1 otherwise
- * 
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Copyright (C) 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #include <asm/asmmacro.h>
 
-/* If a fault occurs, r8 gets set to -EFAULT and r9 gets cleared.  */
-#define EX(x...)				\
-	.section __ex_table,"a";		\
-	data4 @gprel(99f);			\
-	data4 (.Lexit-99f)|1;			\
-	.previous				\
-99:	x;
-
-	.text
-	.psr abi64
-	.psr lsb
-	.lsb
-
 GLOBAL_ENTRY(__strnlen_user)
-	UNW(.prologue)
+	.prologue
 	alloc r2=ar.pfs,2,0,0,0
-	UNW(.save ar.lc, r16)
+	.save ar.lc, r16
 	mov r16=ar.lc			// preserve ar.lc
 
-	UNW(.body)
+	.body
 
 	add r3=-1,in1
 	;;
 	mov ar.lc=r3
 	mov r9=0
-
+	;;
 	// XXX braindead strlen loop---this needs to be optimized
 .Loop1:
-	EX(ld1 r8=[in0],1)
+	EXCLR(.Lexit, ld1 r8=[in0],1)
 	add r9=1,r9
 	;;
 	cmp.eq p6,p0=r8,r0
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/lib/swiotlb.c linux/arch/ia64/lib/swiotlb.c
--- v2.4.3/linux/arch/ia64/lib/swiotlb.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/lib/swiotlb.c	Thu Apr  5 12:51:47 2001
@@ -11,6 +11,7 @@
  */
 
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
@@ -50,14 +51,14 @@
 static unsigned int io_tlb_index;
 
 /*
- * We need to save away the original address corresponding to a mapped entry for the sync 
+ * We need to save away the original address corresponding to a mapped entry for the sync
  * operations.
  */
 static unsigned char **io_tlb_orig_addr;
 
 /*
  * Protect the above data structures in the map and unmap calls
- */ 
+ */
 static spinlock_t io_tlb_lock = SPIN_LOCK_UNLOCKED;
 
 static int __init
@@ -132,7 +133,7 @@
 	{
 		wrap = index = ALIGN(io_tlb_index, stride);
 
-		if (index >= io_tlb_nslabs) 
+		if (index >= io_tlb_nslabs)
 			wrap = index = 0;
 
 		do {
@@ -164,12 +165,12 @@
 		} while (index != wrap);
 
 		/*
-		 * XXX What is a suitable recovery mechanism here?  We cannot 
+		 * XXX What is a suitable recovery mechanism here?  We cannot
 		 * sleep because we are called from with in interrupts!
 		 */
 		panic("map_single: could not allocate software IO TLB (%ld bytes)", size);
-found:
 	}
+  found:
 	spin_unlock_irqrestore(&io_tlb_lock, flags);
 
 	/*
@@ -199,9 +200,9 @@
 	 */
 	if ((direction == PCI_DMA_FROMDEVICE) || (direction == PCI_DMA_BIDIRECTIONAL))
 		/*
- 	 	 * bounce... copy the data back into the original buffer * and delete the
- 	 	 * bounce buffer.
- 	 	 */
+		 * bounce... copy the data back into the original buffer * and delete the
+		 * bounce buffer.
+		 */
 		memcpy(buffer, dma_addr, size);
 
 	/*
@@ -236,9 +237,9 @@
 	char *buffer = io_tlb_orig_addr[index];
 
 	/*
-  	 * bounce... copy the data back into/from the original buffer
+	 * bounce... copy the data back into/from the original buffer
 	 * XXX How do you handle PCI_DMA_BIDIRECTIONAL here ?
- 	 */
+	 */
 	if (direction == PCI_DMA_FROMDEVICE)
 		memcpy(buffer, dma_addr, size);
 	else if (direction == PCI_DMA_TODEVICE)
@@ -298,8 +299,8 @@
 		 */
 		return pci_addr;
 
-	/* 
-	 * get a bounce buffer: 
+	/*
+	 * get a bounce buffer:
 	 */
 	pci_addr = virt_to_phys(map_single(hwdev, ptr, size, direction));
 
@@ -325,12 +326,8 @@
 	pg_addr = PAGE_ALIGN((unsigned long) addr);
 	end = (unsigned long) addr + size;
 	while (pg_addr + PAGE_SIZE <= end) {
-#if 0
-		set_bit(PG_arch_1, virt_to_page(pg_addr));
-#else
-		if (!VALID_PAGE(virt_to_page(pg_addr)))
-			printk("Invalid addr %lx!!!\n", pg_addr);
-#endif
+		struct page *page = virt_to_page(pg_addr);
+		set_bit(PG_arch_1, &page->flags);
 		pg_addr += PAGE_SIZE;
 	}
 }
@@ -454,3 +451,14 @@
 {
 	return virt_to_phys(sg->address);
 }
+
+EXPORT_SYMBOL(swiotlb_init);
+EXPORT_SYMBOL(swiotlb_map_single);
+EXPORT_SYMBOL(swiotlb_unmap_single);
+EXPORT_SYMBOL(swiotlb_map_sg);
+EXPORT_SYMBOL(swiotlb_unmap_sg);
+EXPORT_SYMBOL(swiotlb_sync_single);
+EXPORT_SYMBOL(swiotlb_sync_sg);
+EXPORT_SYMBOL(swiotlb_dma_address);
+EXPORT_SYMBOL(swiotlb_alloc_consistent);
+EXPORT_SYMBOL(swiotlb_free_consistent);
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/mm/extable.c linux/arch/ia64/mm/extable.c
--- v2.4.3/linux/arch/ia64/mm/extable.c	Sun Feb  6 18:42:40 2000
+++ linux/arch/ia64/mm/extable.c	Thu Apr  5 12:51:47 2001
@@ -1,8 +1,8 @@
 /*
  * Kernel exception handling table support.  Derived from arch/alpha/mm/extable.c.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #include <linux/config.h>
@@ -43,14 +43,22 @@
         return 0;
 }
 
-register unsigned long gp __asm__("gp");
+#ifndef CONFIG_MODULE
+register unsigned long main_gp __asm__("gp");
+#endif
 
-const struct exception_table_entry *
+struct exception_fixup
 search_exception_table (unsigned long addr)
 {
+	const struct exception_table_entry *entry;
+	struct exception_fixup fix = { 0 };
+
 #ifndef CONFIG_MODULE
 	/* There is only the kernel to search.  */
-	return search_one_table(__start___ex_table, __stop___ex_table - 1, addr - gp);
+	entry = search_one_table(__start___ex_table, __stop___ex_table - 1, addr - main_gp);
+	if (entry)
+		fix.cont = entry->cont + main_gp;
+	return fix;
 #else
 	struct exception_table_entry *ret;
 	/* The kernel is the last "module" -- no need to treat it special. */
@@ -59,10 +67,22 @@
 	for (mp = module_list; mp ; mp = mp->next) {
 		if (!mp->ex_table_start)
 			continue;
-		ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr - mp->gp);
-		if (ret)
-			return ret;
+		entry = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr - mp->gp);
+		if (entry) {
+			fix.cont = entry->cont + mp->gp;
+			return fix;
+		}
 	}
-	return 0;
 #endif
+	return fix;
+}
+
+void
+handle_exception (struct pt_regs *regs, struct exception_fixup fix)
+{
+	regs->r8 = -EFAULT;
+	if (fix.cont & 4)
+		regs->r9 = 0;
+	regs->cr_iip = (long) fix.cont & ~0xf;
+	ia64_psr(regs)->ri = fix.cont & 0x3;		/* set continuation slot number */
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/mm/fault.c linux/arch/ia64/mm/fault.c
--- v2.4.3/linux/arch/ia64/mm/fault.c	Mon Mar 19 12:35:10 2001
+++ linux/arch/ia64/mm/fault.c	Thu Apr  5 12:51:47 2001
@@ -47,7 +47,7 @@
 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
 {
 	struct mm_struct *mm = current->mm;
-	const struct exception_table_entry *fix;
+	struct exception_fixup fix;
 	struct vm_area_struct *vma, *prev_vma;
 	struct siginfo si;
 	int signal = SIGSEGV;
@@ -163,14 +163,13 @@
 		return;
 	}
 
+#ifdef GAS_HAS_LOCAL_TAGS
+	fix = search_exception_table(regs->cr_iip + ia64_psr(regs)->ri);
+#else
 	fix = search_exception_table(regs->cr_iip);
-	if (fix) {
-		regs->r8 = -EFAULT;
-		if (fix->skip & 1) {
-			regs->r9 = 0;
-		}
-		regs->cr_iip += ((long) fix->skip) & ~15;
-		regs->cr_ipsr &= ~IA64_PSR_RI;	/* clear exception slot number */
+#endif
+	if (fix.cont) {
+		handle_exception(regs, fix);
 		return;
 	}
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/mm/init.c linux/arch/ia64/mm/init.c
--- v2.4.3/linux/arch/ia64/mm/init.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/mm/init.c	Thu Apr  5 12:51:47 2001
@@ -1,8 +1,8 @@
 /*
  * Initialize MMU support.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -23,116 +23,33 @@
 #include <asm/pgalloc.h>
 #include <asm/sal.h>
 #include <asm/system.h>
+#include <asm/uaccess.h>
 
 /* References to section boundaries: */
 extern char _stext, _etext, _edata, __init_begin, __init_end;
 
-/*
- * These are allocated in head.S so that we get proper page alignment.
- * If you change the size of these then change head.S as well.
- */
-extern char empty_bad_page[PAGE_SIZE];
-extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD];
-extern pte_t empty_bad_pte_table[PTRS_PER_PTE];
-
 extern void ia64_tlb_init (void);
 
-static unsigned long totalram_pages;
-
-/*
- * Fill in empty_bad_pmd_table with entries pointing to
- * empty_bad_pte_table and return the address of this PMD table.
- */
-static pmd_t *
-get_bad_pmd_table (void)
-{
-	pmd_t v;
-	int i;
-
-	pmd_set(&v, empty_bad_pte_table);
+unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
 
-	for (i = 0; i < PTRS_PER_PMD; ++i)
-		empty_bad_pmd_table[i] = v;
-
-	return empty_bad_pmd_table;
-}
-
-/*
- * Fill in empty_bad_pte_table with PTEs pointing to empty_bad_page
- * and return the address of this PTE table.
- */
-static pte_t *
-get_bad_pte_table (void)
-{
-	pte_t v;
-	int i;
-
-	set_pte(&v, pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED)));
-
-	for (i = 0; i < PTRS_PER_PTE; ++i)
-		empty_bad_pte_table[i] = v;
-
-	return empty_bad_pte_table;
-}
-
-void
-__handle_bad_pgd (pgd_t *pgd)
-{
-	pgd_ERROR(*pgd);
-	pgd_set(pgd, get_bad_pmd_table());
-}
-
-void
-__handle_bad_pmd (pmd_t *pmd)
-{
-	pmd_ERROR(*pmd);
-	pmd_set(pmd, get_bad_pte_table());
-}
-
-/*
- * Allocate and initialize an L3 directory page and set
- * the L2 directory entry PMD to the newly allocated page.
- */
-pte_t*
-get_pte_slow (pmd_t *pmd, unsigned long offset)
-{
-	pte_t *pte;
-
-	pte = (pte_t *) __get_free_page(GFP_KERNEL);
-	if (pmd_none(*pmd)) {
-		if (pte) {
-			/* everything A-OK */
-			clear_page(pte);
-			pmd_set(pmd, pte);
-			return pte + offset;
-		}
-		pmd_set(pmd, get_bad_pte_table());
-		return NULL;
-	}
-	free_page((unsigned long) pte);
-	if (pmd_bad(*pmd)) {
-		__handle_bad_pmd(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + offset;
-}
+static unsigned long totalram_pages;
 
 int
 do_check_pgt_cache (int low, int high)
 {
 	int freed = 0;
 
-        if (pgtable_cache_size > high) {
-                do {
-                        if (pgd_quicklist)
-                                free_page((unsigned long)get_pgd_fast()), ++freed;
-                        if (pmd_quicklist)
-                                free_page((unsigned long)get_pmd_fast()), ++freed;
-                        if (pte_quicklist)
-                                free_page((unsigned long)get_pte_fast()), ++freed;
-                } while (pgtable_cache_size > low);
-        }
-        return freed;
+	if (pgtable_cache_size > high) {
+		do {
+			if (pgd_quicklist)
+				free_page((unsigned long)pgd_alloc_one_fast()), ++freed;
+			if (pmd_quicklist)
+				free_page((unsigned long)pmd_alloc_one_fast(0, 0)), ++freed;
+			if (pte_quicklist)
+				free_page((unsigned long)pte_alloc_one_fast(0, 0)), ++freed;
+		} while (pgtable_cache_size > low);
+	}
+	return freed;
 }
 
 /*
@@ -188,12 +105,12 @@
 {
 	/*
 	 * EFI uses 4KB pages while the kernel can use 4KB  or bigger.
-	 * Thus EFI and the kernel may have different page sizes. It is 
-	 * therefore possible to have the initrd share the same page as 
-	 * the end of the kernel (given current setup). 
+	 * Thus EFI and the kernel may have different page sizes. It is
+	 * therefore possible to have the initrd share the same page as
+	 * the end of the kernel (given current setup).
 	 *
 	 * To avoid freeing/using the wrong page (kernel sized) we:
-	 * 	- align up the beginning of initrd
+	 *	- align up the beginning of initrd
 	 *	- keep the end untouched
 	 *
 	 *  |             |
@@ -201,8 +118,8 @@
 	 *  |             |
 	 *  |             |
 	 *  |             | 9000
-	 *  |/////////////| 
-	 *  |/////////////| 
+	 *  |/////////////|
+	 *  |/////////////|
 	 *  |=============| 8000
 	 *  |///INITRD////|
 	 *  |/////////////|
@@ -211,9 +128,9 @@
 	 *  |KKKKKKKKKKKKK|
 	 *  |=============| 6000
 	 *  |KKKKKKKKKKKKK|
-	 *  |KKKKKKKKKKKKK| 
+	 *  |KKKKKKKKKKKKK|
 	 *  K=kernel using 8KB pages
-	 * 
+	 *
 	 * In this example, we must free page 8000 ONLY. So we must align up
 	 * initrd_start and keep initrd_end as is.
 	 */
@@ -286,52 +203,59 @@
 		       page_address(page));
 
 	pgd = pgd_offset_k(address);		/* note: this is NOT pgd_offset()! */
-	pmd = pmd_alloc(pgd, address);
-	if (!pmd) {
-		__free_page(page);
-		panic("Out of memory.");
-		return 0;
-	}
-	pte = pte_alloc(pmd, address);
-	if (!pte) {
-		__free_page(page);
-		panic("Out of memory.");
-		return 0;
-	}
-	if (!pte_none(*pte)) {
-		pte_ERROR(*pte);
-		__free_page(page);
-		return 0;
+
+	spin_lock(&init_mm.page_table_lock);
+	{
+		pmd = pmd_alloc(&init_mm, pgd, address);
+		if (!pmd)
+			goto out;
+		pte = pte_alloc(&init_mm, pmd, address);
+		if (!pte)
+			goto out;
+		if (!pte_none(*pte)) {
+			pte_ERROR(*pte);
+			goto out;
+		}
+		flush_page_to_ram(page);
+		set_pte(pte, mk_pte(page, PAGE_GATE));
 	}
-	flush_page_to_ram(page);
-	set_pte(pte, mk_pte(page, PAGE_GATE));
+  out:	spin_unlock(&init_mm.page_table_lock);
 	/* no need for flush_tlb */
 	return page;
 }
 
 void __init
-ia64_rid_init (void)
+ia64_mmu_init (void)
 {
 	unsigned long flags, rid, pta, impl_va_bits;
+	extern void __init tlb_init (void);
 #ifdef CONFIG_DISABLE_VHPT
 #	define VHPT_ENABLE_BIT	0
 #else
 #	define VHPT_ENABLE_BIT	1
 #endif
 
-	/* Set up the kernel identity mappings (regions 6 & 7) and the vmalloc area (region 5): */
+	/*
+	 * Set up the kernel identity mapping for regions 6 and 5.  The mapping for region
+	 * 7 is setup up in _start().
+	 */
 	ia64_clear_ic(flags);
 
 	rid = ia64_rid(IA64_REGION_ID_KERNEL, __IA64_UNCACHED_OFFSET);
-	ia64_set_rr(__IA64_UNCACHED_OFFSET, (rid << 8) | (_PAGE_SIZE_256M << 2));
-
-	rid = ia64_rid(IA64_REGION_ID_KERNEL, PAGE_OFFSET);
-	ia64_set_rr(PAGE_OFFSET, (rid << 8) | (_PAGE_SIZE_256M << 2));
+	ia64_set_rr(__IA64_UNCACHED_OFFSET, (rid << 8) | (_PAGE_SIZE_64M << 2));
 
 	rid = ia64_rid(IA64_REGION_ID_KERNEL, VMALLOC_START);
 	ia64_set_rr(VMALLOC_START, (rid << 8) | (PAGE_SHIFT << 2) | 1);
 
+	/* ensure rr6 is up-to-date before inserting the PERCPU_ADDR translation: */
+	ia64_srlz_d();
+
+	ia64_itr(0x2, IA64_TR_PERCPU_DATA, PERCPU_ADDR,
+		 pte_val(mk_pte_phys(__pa(&cpu_data[smp_processor_id()]), PAGE_KERNEL)),
+		 PAGE_SHIFT);
+
 	__restore_flags(flags);
+	ia64_srlz_i();
 
 	/*
 	 * Check if the virtually mapped linear page table (VMLPT) overlaps with a mapped
@@ -356,7 +280,7 @@
 #	define vmlpt_bits		(impl_va_bits - PAGE_SHIFT + pte_bits)
 #	define POW2(n)			(1ULL << (n))
 
-	impl_va_bits = ffz(~my_cpu_data.unimpl_va_mask);
+	impl_va_bits = ffz(~(local_cpu_data->unimpl_va_mask | (7UL << 61)));
 
 	if (impl_va_bits < 51 || impl_va_bits > 61)
 		panic("CPU has bogus IMPL_VA_MSB value of %lu!\n", impl_va_bits - 1);
@@ -374,6 +298,8 @@
 	 * enabled.
 	 */
 	ia64_set_pta(pta | (0 << 8) | (vmlpt_bits << 2) | VHPT_ENABLE_BIT);
+
+	ia64_tlb_init();
 }
 
 /*
@@ -390,7 +316,7 @@
 
 	memset(zones_size, 0, sizeof(zones_size));
 
-	max_dma = (PAGE_ALIGN(MAX_DMA_ADDRESS) >> PAGE_SHIFT);
+	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 	if (max_low_pfn < max_dma)
 		zones_size[ZONE_DMA] = max_low_pfn;
 	else {
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/mm/tlb.c linux/arch/ia64/mm/tlb.c
--- v2.4.3/linux/arch/ia64/mm/tlb.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/mm/tlb.c	Thu Apr  5 12:51:47 2001
@@ -1,11 +1,11 @@
 /*
  * TLB support routines.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  *
- * 08/02/00 A. Mallick <asit.k.mallick@intel.com>	
- *		Modified RID allocation for SMP 
+ * 08/02/00 A. Mallick <asit.k.mallick@intel.com>
+ *		Modified RID allocation for SMP
  *          Goutham Rao <goutham.rao@intel.com>
  *              IPI based ptc implementation and A-step IPI implementation.
  */
@@ -41,7 +41,7 @@
 };
 
 /*
- * Seralize usage of ptc.g 
+ * Seralize usage of ptc.g
  */
 spinlock_t ptcg_lock = SPIN_LOCK_UNLOCKED; /* see <asm/pgtable.h> */
 
@@ -49,7 +49,7 @@
 
 #include <linux/irq.h>
 
-unsigned long 	flush_end, flush_start, flush_nbits, flush_rid;
+unsigned long	flush_end, flush_start, flush_nbits, flush_rid;
 atomic_t flush_cpu_count;
 
 /*
@@ -71,7 +71,7 @@
 	if (!(flags & IA64_PSR_I)) {
 		saved_tpr = ia64_get_tpr();
 		ia64_srlz_d();
-		ia64_set_tpr(IPI_IRQ - 16);
+		ia64_set_tpr(IA64_IPI_VECTOR - 16);
 		ia64_srlz_d();
 		local_irq_enable();
 	}
@@ -97,13 +97,14 @@
 	/*
 	 * Wait for other CPUs to finish purging entries.
 	 */
-#if (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC))
+#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC)
 	{
+		extern void smp_resend_flush_tlb (void);
 		unsigned long start = ia64_get_itc();
+
 		while (atomic_read(&flush_cpu_count) > 0) {
-			if ((ia64_get_itc() - start) > 40000UL) {
-				atomic_set(&flush_cpu_count, smp_num_cpus - 1);
-				smp_send_flush_tlb();
+			if ((ia64_get_itc() - start) > 400000UL) {
+				smp_resend_flush_tlb();
 				start = ia64_get_itc();
 			}
 		}
@@ -148,7 +149,7 @@
 		if (tsk_context == ia64_ctx.next) {
 			if (++ia64_ctx.next >= ia64_ctx.limit) {
 				/* empty range: reset the range limit and start over */
-				if (ia64_ctx.next > max_ctx) 
+				if (ia64_ctx.next > max_ctx)
 					ia64_ctx.next = 300;
 				ia64_ctx.limit = max_ctx + 1;
 				goto repeat;
@@ -166,11 +167,11 @@
 {
 	unsigned long i, j, flags, count0, count1, stride0, stride1, addr;
 
-	addr    = my_cpu_data.ptce_base;
-	count0  = my_cpu_data.ptce_count[0];
-	count1  = my_cpu_data.ptce_count[1];
-	stride0 = my_cpu_data.ptce_stride[0];
-	stride1 = my_cpu_data.ptce_stride[1];
+	addr    = local_cpu_data->ptce_base;
+	count0  = local_cpu_data->ptce_count[0];
+	count1  = local_cpu_data->ptce_count[1];
+	stride0 = local_cpu_data->ptce_stride[0];
+	stride1 = local_cpu_data->ptce_stride[1];
 
 	local_irq_save(flags);
 	for (i = 0; i < count0; ++i) {
@@ -249,11 +250,11 @@
 	ia64_ptce_info_t ptce_info;
 
 	ia64_get_ptce(&ptce_info);
-	my_cpu_data.ptce_base = ptce_info.base;
-	my_cpu_data.ptce_count[0] = ptce_info.count[0];
-	my_cpu_data.ptce_count[1] = ptce_info.count[1];
-	my_cpu_data.ptce_stride[0] = ptce_info.stride[0];
-	my_cpu_data.ptce_stride[1] = ptce_info.stride[1];
+	local_cpu_data->ptce_base = ptce_info.base;
+	local_cpu_data->ptce_count[0] = ptce_info.count[0];
+	local_cpu_data->ptce_count[1] = ptce_info.count[1];
+	local_cpu_data->ptce_stride[0] = ptce_info.stride[0];
+	local_cpu_data->ptce_stride[1] = ptce_info.stride[1];
 
 	__flush_tlb_all();		/* nuke left overs from bootstrapping... */
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/Makefile linux/arch/ia64/sn/Makefile
--- v2.4.3/linux/arch/ia64/sn/Makefile	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/Makefile	Thu Apr  5 12:51:47 2001
@@ -8,12 +8,11 @@
 EXTRA_CFLAGS	:= -DSN -DLANGUAGE_C=1 -D_LANGUAGE_C=1 -I. -DBRINGUP \
 		   -DDIRECT_L1_CONSOLE -DNUMA_BASE -DSIMULATED_KLGRAPH \
 		   -DNUMA_MIGR_CONTROL -DLITTLE_ENDIAN -DREAL_HARDWARE \
-		   -DNEW_INTERRUPTS -DCONFIG_IA64_SGI_IO
+		   -DNEW_INTERRUPTS
 all: sn.a
 
 O_TARGET        = sn.a
-O_HEADERS       =
-O_OBJS          = sn1/sn1.a
+obj-y           = sn1/sn1.a
 
 clean::
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/fprom/Makefile linux/arch/ia64/sn/fprom/Makefile
--- v2.4.3/linux/arch/ia64/sn/fprom/Makefile	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/fprom/Makefile	Thu Apr  5 12:51:47 2001
@@ -13,6 +13,7 @@
 LIB     = ../../lib/lib.a
 
 OBJ=fpromasm.o main.o  fw-emu.o fpmem.o
+obj-y=fprom
 
 fprom: $(OBJ)
 	$(LD) -static -Tfprom.lds -o fprom $(OBJ) $(LIB)
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/fprom/fw-emu.c linux/arch/ia64/sn/fprom/fw-emu.c
--- v2.4.3/linux/arch/ia64/sn/fprom/fw-emu.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/fprom/fw-emu.c	Thu Apr 12 12:16:35 2001
@@ -8,6 +8,7 @@
  * Copyright (C) 2000 Silicon Graphics, Inc.
  * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com)
  */
+
 #include <asm/efi.h>
 #include <asm/pal.h>
 #include <asm/sal.h>
@@ -62,6 +63,7 @@
 func_ptr_t	ap_entry;
 
 
+static efi_runtime_services_t    *efi_runtime_p;
 static char fw_mem[(  sizeof(efi_system_table_t)
 		    + sizeof(efi_runtime_services_t)
 		    + NUM_EFI_DESCS*sizeof(efi_config_table_t)
@@ -88,8 +90,8 @@
 	.text
 	.proc pal_emulator_static
 pal_emulator_static:
-	mov r8=-1
-	cmp.eq p6,p7=6,r28		/* PAL_PTCE_INFO */
+	mov r8=-1;;
+	cmp.eq p6,p7=6,r28;;		/* PAL_PTCE_INFO */
 (p7)	br.cond.sptk.few 1f
 	;;
 	mov r8=0			/* status = 0 */
@@ -98,20 +100,20 @@
 	movl r11=0x1000000000002000	/* stride[0], stride[1] */
 	br.cond.sptk.few rp
 
-1:	cmp.eq p6,p7=14,r28		/* PAL_FREQ_RATIOS */
-(p7)	br.cond.sptk.few 1f
+1:	cmp.eq p6,p7=14,r28;;		/* PAL_FREQ_RATIOS */
+(p7)	br.cond.sptk.few 1f;;
 	mov r8=0			/* status = 0 */
 	movl r9 =0x100000064		/* proc_ratio (1/100) */
 	movl r10=0x100000100		/* bus_ratio<<32 (1/256) */
 	movl r11=0x10000000a		/* itc_ratio<<32 (1/100) */
 
-1:	cmp.eq p6,p7=22,r28		/* PAL_MC_DRAIN */
-(p7)	br.cond.sptk.few 1f
+1:	cmp.eq p6,p7=22,r28;;		/* PAL_MC_DRAIN */
+(p7)	br.cond.sptk.few 1f;;
 	mov r8=0
 	br.cond.sptk.few rp
 
-1:	cmp.eq p6,p7=23,r28		/* PAL_MC_EXPECTED */
-(p7)	br.cond.sptk.few 1f
+1:	cmp.eq p6,p7=23,r28;;		/* PAL_MC_EXPECTED */
+(p7)	br.cond.sptk.few 1f;;
 	mov r8=0
 	br.cond.sptk.few rp
 
@@ -256,6 +258,36 @@
 	_fp->gp = __fwtab_pa(base_nasid, _fp->gp);
 }
 
+void
+fix_virt_function_pointer(void *fptr)
+{
+        func_ptr_t      *fp;
+
+        fp = fptr;
+        fp->pc = fp->pc | PAGE_OFFSET;
+        fp->gp = fp->gp | PAGE_OFFSET;
+}
+
+
+int
+efi_set_virtual_address_map(void)
+{
+        efi_runtime_services_t            *runtime;
+
+        runtime = efi_runtime_p;
+        fix_virt_function_pointer((void*)runtime->get_time);
+        fix_virt_function_pointer((void*)runtime->set_time);
+        fix_virt_function_pointer((void*)runtime->get_wakeup_time);
+        fix_virt_function_pointer((void*)runtime->set_wakeup_time);
+        fix_virt_function_pointer((void*)runtime->set_virtual_address_map);
+        fix_virt_function_pointer((void*)runtime->get_variable);
+        fix_virt_function_pointer((void*)runtime->get_next_variable);
+        fix_virt_function_pointer((void*)runtime->set_variable);
+        fix_virt_function_pointer((void*)runtime->get_next_high_mono_count);
+        fix_virt_function_pointer((void*)runtime->reset_system);
+        return EFI_SUCCESS;;
+}
+
 
 void
 sys_fw_init (const char *args, int arglen, int bsp)
@@ -305,7 +337,7 @@
 
 	cp = fw_mem;
 	efi_systab  = (void *) cp; cp += sizeof(*efi_systab);
-	efi_runtime = (void *) cp; cp += sizeof(*efi_runtime);
+	efi_runtime_p = efi_runtime = (void *) cp; cp += sizeof(*efi_runtime);
 	efi_tables  = (void *) cp; cp += NUM_EFI_DESCS*sizeof(*efi_tables);
 	sal_systab  = (void *) cp; cp += sizeof(*sal_systab);
 	sal_ed      = (void *) cp; cp += sizeof(*sal_ed);
@@ -354,7 +386,7 @@
 	efi_runtime->set_time = __fwtab_pa(base_nasid, &efi_unimplemented);
 	efi_runtime->get_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
 	efi_runtime->set_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
-	efi_runtime->set_virtual_address_map = __fwtab_pa(base_nasid, &efi_success);
+	efi_runtime->set_virtual_address_map = __fwtab_pa(base_nasid, &efi_set_virtual_address_map);
 	efi_runtime->get_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
 	efi_runtime->get_next_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
 	efi_runtime->set_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
@@ -370,10 +402,11 @@
 	fix_function_pointer(&efi_get_time);
 	fix_function_pointer(&efi_success);
 	fix_function_pointer(&efi_reset_system);
+	fix_function_pointer(&efi_set_virtual_address_map);
 
 	/* fill in the ACPI system table: */
 	memcpy(acpi_systab->signature, "RSD PTR ", 8);
-	acpi_systab->rsdt = (acpi_rsdt_t*)__fwtab_pa(base_nasid, acpi_rsdt);
+	acpi_systab->rsdt = (struct acpi_rsdt*)__fwtab_pa(base_nasid, acpi_rsdt);
 
 	memcpy(acpi_rsdt->header.signature, "RSDT",4);
 	acpi_rsdt->header.length = sizeof(acpi_rsdt_t);
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/Makefile linux/arch/ia64/sn/io/Makefile
--- v2.4.3/linux/arch/ia64/sn/io/Makefile	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/Makefile	Thu Apr  5 12:51:47 2001
@@ -18,15 +18,15 @@
 EXTRA_CFLAGS	:= -DSN -DLANGUAGE_C=1 -D_LANGUAGE_C=1 -I. -DBRINGUP \
 		   -DDIRECT_L1_CONSOLE -DNUMA_BASE -DSIMULATED_KLGRAPH \
 		   -DNUMA_MIGR_CONTROL -DLITTLE_ENDIAN -DREAL_HARDWARE \
-		   -DNEW_INTERRUPTS -DCONFIG_IA64_SGI_IO
+		   -DNEW_INTERRUPTS
 O_TARGET := sgiio.o
-O_OBJS   := stubs.o sgi_if.o pciio.o pcibr.o xtalk.o xbow.o xswitch.o hubspc.o \
-		klgraph_hack.o io.o hubdev.o \
+obj-y   := stubs.o sgi_if.o pciio.o pcibr.o xtalk.o xbow.o xswitch.o hubspc.o \
+		klgraph_hack.o io.o hubdev.o huberror.o \
 		hcl.o labelcl.o invent.o klgraph.o klconflib.o sgi_io_sim.o \
 		module.o sgi_io_init.o klgraph_hack.o ml_SN_init.o \
-		ml_SN_intr.o ip37.o \
+		ml_SN_intr.o ip37.o pciba.o \
 		ml_iograph.o hcl_util.o cdl.o \
 		mem_refcnt.o devsupport.o alenlist.o pci_bus_cvlink.o \
-		eeprom.o pci.o pci_dma.o l1.o l1_command.o
+		eeprom.o pci.o pci_dma.o l1.o l1_command.o ate_utils.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/alenlist.c linux/arch/ia64/sn/io/alenlist.c
--- v2.4.3/linux/arch/ia64/sn/io/alenlist.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/alenlist.c	Thu Apr  5 12:51:47 2001
@@ -201,8 +201,8 @@
 int alenlist_count=0;		/* Currently allocated Lists */
 int alenlist_chunk_count = 0;	/* Currently allocated chunks */
 int alenlist_cursor_count = 0;	/* Currently allocate cursors */
-#define INCR_COUNT(ptr) atomicAddInt((ptr), 1);
-#define DECR_COUNT(ptr) atomicAddInt((ptr), -1);
+#define INCR_COUNT(ptr) atomic_inc((ptr));
+#define DECR_COUNT(ptr) atomic_dec((ptr));
 #else
 #define INCR_COUNT(ptr)
 #define DECR_COUNT(ptr)
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/cdl.c linux/arch/ia64/sn/io/cdl.c
--- v2.4.3/linux/arch/ia64/sn/io/cdl.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/cdl.c	Thu Apr  5 12:51:47 2001
@@ -67,7 +67,7 @@
 void
 cdl_del(cdl_p reg)
 {
-	printk("SGI IO INFRASTRUCTURE - cdl_del not supported.\n");
+	return;
 }
 
 /*
@@ -77,7 +77,7 @@
   Do nothing.
  */
 int
-cdl_add_driver(cdl_p reg, int key1, int key2, char *prefix, int flags)
+cdl_add_driver(cdl_p reg, int key1, int key2, char *prefix, int flags, cdl_drv_f *func)
 {
     return 0;
 }
@@ -86,11 +86,9 @@
  * cdl_del_driver: Not supported.
  */
 void
-cdl_del_driver(cdl_p reg,
-	       char *prefix)
+cdl_del_driver(cdl_p reg, char *prefix, cdl_drv_f *func)
 {
-
-	printk("SGI IO INFRASTRUCTURE - cdl_del_driver not supported.\n");
+	return;
 }
 
 /*
@@ -106,7 +104,7 @@
  */
 int
 cdl_add_connpt(cdl_p reg, int part_num, int mfg_num, 
-	       devfs_handle_t connpt)
+	       devfs_handle_t connpt, int drv_flags)
 {
 	int i;
 	
@@ -123,27 +121,12 @@
 			if (sgi_infrastructure_drivers[i].attach) {
 			    return(sgi_infrastructure_drivers[i].attach(connpt));
 			}
-#ifdef BRINGUP
-			/*
-			 * XXX HACK ALERT bypassing fops for now..
-			 */
-			else {
-			    printk("cdl_add_connpt: NEED FOPS FOR OUR DRIVERS!!\n");
-			    printk("cdl_add_connpt: part_num= 0x%x  mfg_num= 0x%x\n",
-				part_num, mfg_num);
-			    return(-1);
-			}
-#endif /* BRINGUP */
 		} else {
 			continue;
 		}
-
-		printk("**** cdl_add_connpt: driver not found for part_num %d mfg_num %d ****\n", part_num, mfg_num);
-
-		return(-1);
 	}	
-	if ( (i == MAX_SGI_IO_INFRA_DRVR) ) 
-		printk("**** cdl_add_connpt: Driver not found for part_num 0x%x mfg_num 0x%x ****\n", part_num, mfg_num);
+
+	/* printk("WARNING: cdl_add_connpt: Driver not found for part_num 0x%x mfg_num 0x%x\n", part_num, mfg_num); */
 
 	return (0);
 }
@@ -151,11 +134,11 @@
 /*
  * cdl_del_connpt: Not implemented.
  */
-void
-cdl_del_connpt(cdl_p reg, int key1, int key2, devfs_handle_t connpt)
+int
+cdl_del_connpt(cdl_p reg, int key1, int key2, devfs_handle_t connpt, int drv_flags)
 {
 
-	printk("SGI IO INFRASTRUCTURE - cdl_del_cdl_del_connpt not supported.\n");
+	return(0);
 }
 
 /*
@@ -166,65 +149,54 @@
 	    char *prefix,
 	    cdl_iter_f * func)
 {
-
-	printk("SGI IO INFRASTRUCTURE - cdl_iterate not supported.\n");
+	return;
 }
 
 async_attach_t 
 async_attach_new(void)
 {
 
-	printk("SGI IO INFRASTRUCTURE - async_attach_new not supported.\n");
 	return(0);
 }
 
 void 
 async_attach_free(async_attach_t aa)
 {
-	printk("SGI IO INFRASTRUCTURE - async_attach_free not supported.\n");
+	return;
 }
 
 async_attach_t 
 async_attach_get_info(devfs_handle_t vhdl)
 {
 
-	printk("SGI IO INFRASTRUCTURE - async_attach_get_info not supported.\n");
 	return(0);
 }
 
 void            
 async_attach_add_info(devfs_handle_t vhdl, async_attach_t aa)
 {
-	printk("SGI IO INFRASTRUCTURE - async_attach_add_info not supported.\n");
+	return;
 
 }
 
 void            
 async_attach_del_info(devfs_handle_t vhdl)
 {
-
-	printk("SGI IO INFRASTRUCTURE - async_attach_del_info not supported.\n");
-
+	return;
 }
 
 void async_attach_signal_start(async_attach_t aa)
 {
-
-	printk("SGI IO INFRASTRUCTURE - async_attach_signal_start not supported.\n");
-
+	return;
 }
 
 void async_attach_signal_done(async_attach_t aa)
 {
-
-	printk("SGI IO INFRASTRUCTURE - async_attach_signal_done not supported.\n");
-
+	return;
 }
 
 void async_attach_waitall(async_attach_t aa)
 {
-
-	printk("SGI IO INFRASTRUCTURE - async_attach_waitall not supported.\n");
-
+	return;
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/devsupport.c linux/arch/ia64/sn/io/devsupport.c
--- v2.4.3/linux/arch/ia64/sn/io/devsupport.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/devsupport.c	Thu Apr  5 12:51:47 2001
@@ -1,5 +1,3 @@
-#define ilvt_t int
-
 /* $Id$
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -28,7 +26,7 @@
 /* =====Generic iobus support===== */
 
 /* String table to hold names of interrupts. */
-#ifdef notyet
+#ifdef LATER
 static struct string_table device_desc_string_table;
 #endif
 
@@ -36,7 +34,7 @@
 static void
 device_desc_init(void)
 {
-#ifdef notyet
+#ifdef LATER
 	string_table_init(&device_desc_string_table);
 #endif
 	FIXME("device_desc_init");
@@ -47,7 +45,7 @@
 static device_desc_t
 device_desc_alloc(void)
 {
-#ifdef notyet
+#ifdef LATER
 	device_desc_t device_desc;
 
 	device_desc = (device_desc_t)kmem_zalloc(sizeof(struct device_desc_s), 0);
@@ -69,7 +67,7 @@
 void
 device_desc_free(device_desc_t device_desc)
 {
-#ifdef notyet
+#ifdef LATER
 	if (!(device_desc->flags & D_IS_ASSOC)) /* sanity */
 		kfree(device_desc);
 #endif
@@ -79,7 +77,7 @@
 device_desc_t
 device_desc_dup(devfs_handle_t dev)
 {
-#ifdef notyet
+#ifdef LATER
 	device_desc_t orig_device_desc, new_device_desc;
 
 
@@ -111,7 +109,7 @@
 device_desc_t	
 device_desc_default_get(devfs_handle_t dev)
 {
-#ifdef notyet
+#ifdef LATER
 	graph_error_t rc;
 	device_desc_t device_desc;
 
@@ -130,7 +128,7 @@
 void		
 device_desc_default_set(devfs_handle_t dev, device_desc_t new_device_desc)
 {
-#ifdef notyet
+#ifdef LATER
 	graph_error_t rc;
 	device_desc_t old_device_desc = NULL;
 
@@ -164,7 +162,7 @@
 devfs_handle_t
 device_desc_intr_target_get(device_desc_t device_desc)
 {
-#ifdef notyet
+#ifdef LATER
 	return(device_desc->intr_target);
 #else
 	FIXME("device_desc_intr_target_get");
@@ -175,7 +173,7 @@
 int
 device_desc_intr_policy_get(device_desc_t device_desc)
 {
-#ifdef notyet
+#ifdef LATER
 	return(device_desc->intr_policy);
 #else
 	FIXME("device_desc_intr_policy_get");
@@ -186,7 +184,7 @@
 ilvl_t
 device_desc_intr_swlevel_get(device_desc_t device_desc)
 {
-#ifdef notyet
+#ifdef LATER
 	return(device_desc->intr_swlevel);
 #else
 	FIXME("device_desc_intr_swlevel_get");
@@ -197,7 +195,7 @@
 char *
 device_desc_intr_name_get(device_desc_t device_desc)
 {
-#ifdef notyet
+#ifdef LATER
 	return(device_desc->intr_name);
 #else
 	FIXME("device_desc_intr_name_get");
@@ -208,7 +206,7 @@
 int
 device_desc_flags_get(device_desc_t device_desc)
 {
-#ifdef notyet
+#ifdef LATER
 	return(device_desc->flags);
 #else
 	FIXME("device_desc_flags_get");
@@ -240,7 +238,7 @@
 void
 device_desc_intr_name_set(device_desc_t device_desc, char *name)
 {
-#ifdef notyet
+#ifdef LATER
 	if ( device_desc != (device_desc_t)0 )
 		device_desc->intr_name = string_table_insert(&device_desc_string_table, name);
 #else
@@ -325,7 +323,7 @@
 static void
 dev_admin_registry_init(dev_admin_registry_t *registry)
 {
-#ifdef notyet
+#ifdef LATER
 	if ( registry != (dev_admin_registry_t *)0 )
 		DEV_ADMIN_REGISTRY_INITLOCK(&registry->reg_lock,
 				    "dev_admin_registry_lock");
@@ -349,7 +347,7 @@
 		       char			*name,
 		       char			*val)
 {
-#ifdef notyet
+#ifdef LATER
 	dev_admin_list_t	*reg_entry;
 	dev_admin_list_t	*scan = 0;
 
@@ -404,7 +402,7 @@
 static char *
 dev_admin_registry_find(dev_admin_registry_t *registry,char *name)
 {
-#ifdef notyet
+#ifdef LATER
 	dev_admin_list_t	*scan = 0;
 	
 	DEV_ADMIN_REGISTRY_RDLOCK(&registry->reg_lock);
@@ -433,7 +431,7 @@
 device_admin_info_get(devfs_handle_t	dev_vhdl,
 		      char		*info_lbl)
 {
-#ifdef notyet
+#ifdef LATER
 	char		*info = 0;
 
 	/* return value need not be GRAPH_SUCCESS as the labelled
@@ -460,7 +458,7 @@
 		      char		*dev_info_lbl,
 		      char		*dev_info_val)
 {
-#ifdef notyet
+#ifdef LATER
 	graph_error_t		rv;
 	arbitrary_info_t	old_info;
 
@@ -570,7 +568,7 @@
 device_driver_admin_info_get(char		*driver_prefix,
 			     char		*driver_info_lbl)
 {
-#ifdef notyet
+#ifdef LATER
 	device_driver_t driver;
 
 	driver = device_driver_get(driver_prefix);
@@ -592,7 +590,7 @@
 			     char		*driver_info_lbl,
 			     char		*driver_info_val)
 {
-#ifdef notyet
+#ifdef LATER
 	device_driver_t driver;
 
 	driver = device_driver_get(driver_prefix);
@@ -623,7 +621,7 @@
 void
 device_admin_table_init(void)
 {
-#ifdef notyet
+#ifdef LATER
 	extended_dev_admin_table_size = 0;
 	mrinit(&extended_dev_admin_table_lock,
 	       "extended_dev_admin_table_lock");
@@ -638,7 +636,7 @@
 void
 device_admin_table_update(char *name,char *label,char *value)
 {
-#ifdef notyet
+#ifdef LATER
 	dev_admin_info_t	*p;
 
 	mrupdate(&extended_dev_admin_table_lock);
@@ -678,7 +676,7 @@
 void
 device_driver_admin_table_init(void)
 {
-#ifdef notyet
+#ifdef LATER
 	extended_drv_admin_table_size = 0;
 	mrinit(&extended_drv_admin_table_lock,
 	       "extended_drv_admin_table_lock");
@@ -693,7 +691,7 @@
 void
 device_driver_admin_table_update(char *name,char *label,char *value)
 {
-#ifdef notyet
+#ifdef LATER
 	dev_admin_info_t	*p;
 
 	mrupdate(&extended_dev_admin_table_lock);
@@ -730,7 +728,7 @@
 void
 device_admin_info_update(devfs_handle_t	dev_vhdl)
 {
-#ifdef notyet
+#ifdef LATER
 	int			i = 0;
 	dev_admin_info_t	*scan;
 	devfs_handle_t		scan_vhdl;
@@ -779,7 +777,7 @@
 void
 device_driver_admin_info_update(device_driver_t	driver)
 {
-#ifdef notyet
+#ifdef LATER
 	int			i = 0;
 	dev_admin_info_t	*scan;
 
@@ -823,7 +821,7 @@
 */
 
 #define DEVICE_DRIVER_HASH_SIZE 32
-#ifdef notyet
+#ifdef LATER
 lock_t device_driver_lock[DEVICE_DRIVER_HASH_SIZE];
 device_driver_t device_driver_hash[DEVICE_DRIVER_HASH_SIZE];
 static struct string_table driver_prefix_string_table;
@@ -835,7 +833,7 @@
 void
 device_driver_init(void)
 {
-#ifdef notyet
+#ifdef LATER
 	int i;
 	extern void alenlist_init(void);
 	extern void hwgraph_init(void);
@@ -849,7 +847,7 @@
 	string_table_init(&driver_prefix_string_table);
 
 	for (i=0; i<DEVICE_DRIVER_HASH_SIZE; i++) {
-		spinlock_init(&device_driver_lock[i], "devdrv");
+		spin_lock_init(&device_driver_lock[i]);
 		device_driver_hash[i] = NULL;
 	}
 
@@ -877,7 +875,7 @@
 static int
 driver_prefix_hash(char *prefix)
 {
-#ifdef notyet
+#ifdef LATER
 	int accum = 0;
 	char nextchar;
 
@@ -903,10 +901,10 @@
 device_driver_t
 device_driver_alloc(char *prefix)
 {
-#ifdef notyet
+#ifdef LATER
 	int which_hash;
 	device_driver_t new_driver;
-	int s;
+	unsigned long s;
 		
 	which_hash = driver_prefix_hash(prefix);
 
@@ -964,9 +962,9 @@
 void
 device_driver_free(device_driver_t driver)
 {
-#ifdef notyet
+#ifdef LATER
 	int which_hash;
-	int s;
+	unsigned long s;
 
 	if (!driver)
 		return;
@@ -1027,10 +1025,10 @@
 device_driver_t
 device_driver_get(char *prefix)
 {
-#ifdef notyet
+#ifdef LATER
 	int which_hash;
 	device_driver_t drvscan;
-	int s;
+	unsigned long s;
 
 	if (prefix == NULL)
 		return(NULL);
@@ -1060,7 +1058,7 @@
 device_driver_t
 device_driver_getbydev(devfs_handle_t device)
 {
-#ifdef notyet
+#ifdef LATER
 	struct bdevsw *my_bdevsw;
 	struct cdevsw *my_cdevsw;
 
@@ -1093,7 +1091,7 @@
 			struct bdevsw *my_bdevsw,
 			struct cdevsw *my_cdevsw)
 {
-#ifdef notyet
+#ifdef LATER
 	int i;
 
 	if (!driver)
@@ -1194,7 +1192,7 @@
 void 
 device_info_set(devfs_handle_t device, void *info)
 {
-#ifdef notyet
+#ifdef LATER
 	hwgraph_fastinfo_set(device, (arbitrary_info_t)info);
 #endif
 	FIXME("device_info_set");
@@ -1207,7 +1205,7 @@
 void *
 device_info_get(devfs_handle_t device)
 {
-#ifdef notyet
+#ifdef LATER
 	return((void *)hwgraph_fastinfo_get(device));
 #else
 	FIXME("device_info_get");
@@ -1222,7 +1220,7 @@
 int
 device_driver_sysgen_thread_pri_get(char *dev_prefix)
 {
-#ifdef notyet
+#ifdef LATER
 	int pri;
 	char *pri_s;
 	char *class;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/eeprom.c linux/arch/ia64/sn/io/eeprom.c
--- v2.4.3/linux/arch/ia64/sn/io/eeprom.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/eeprom.c	Thu Apr  5 12:51:47 2001
@@ -53,7 +53,6 @@
 #include <asm/sn/labelcl.h>
 #include <asm/sn/eeprom.h>
 #include <asm/sn/ksys/i2c.h>
-#include <asm/sn/cmn_err.h>
 /* #include <sys/SN/SN1/ip27log.h> */
 #include <asm/sn/router.h>
 #include <asm/sn/module.h>
@@ -949,6 +948,7 @@
 #else
     char msg[BRL1_QSIZE]; 	    /* message buffer */
     int len;              	    /* number of bytes used in message buffer */
+    int resp;                       /* l1 response code */
     int spd_len = EEPROM_CHUNKSIZE; /* remaining bytes in spd record */
     int offset = 0;		    /* current offset into spd record */
     char *spd_p = spd->bytes;	    /* "thumb" for writing to spd */
@@ -981,11 +981,26 @@
 	}
 
 	/* check response */
-	if( sc_interpret_resp( msg, 5, 
+	if( (resp = sc_interpret_resp( msg, 5, 
 			       L1_ARG_INT, &spd_len,
-			       L1_ARG_UNKNOWN, &len, spd_p ) < 0 )
+			       L1_ARG_UNKNOWN, &len, spd_p )) < 0 )
 	{
-	    return( EEP_L1 );
+            /*
+             * translate l1 response code to eeprom.c error codes:
+             * The L1 response will be L1_RESP_NAVAIL if the spd
+             * can't be read (i.e. the spd isn't physically there). It will
+             * return L1_RESP_INVAL if the spd exists, but fails the checksum
+             * test because the eeprom wasn't programmed, programmed incorrectly,
+             * or corrupted. L1_RESP_NAVAIL indicates the eeprom is likely not present,
+             * whereas L1_RESP_INVAL indicates the eeprom is present, but the data is
+             * invalid.
+             */
+            if(resp == L1_RESP_INVAL) {
+                resp = EEP_BAD_CHECKSUM;
+            } else {
+                resp = EEP_L1;
+            }
+            return( resp );
 	}
 
 	if( spd_len > EEPROM_CHUNKSIZE )
@@ -1201,7 +1216,9 @@
 #else
     int r;
     uint64_t uid = 0;
+#ifdef LOG_GETENV
     char uid_str[32];
+#endif
     int l1_compt, subch;
 
     if ( IS_RUNNING_ON_SIMULATOR() )
@@ -1228,6 +1245,13 @@
     if( (subch = sc_open( scp, L1_ADDR_LOCAL )) < 0 )
 	return EEP_L1;
 
+    if((component & C_DIMM) == C_DIMM) {
+        l1_compt = L1_EEP_DIMM(component & COMPT_MASK);
+        r = read_spd(scp,subch,l1_compt, buf->spd);
+        sc_close(scp,subch);
+        return(r);
+    }
+
     switch( component )
     {
       case C_BRICK:
@@ -1252,13 +1276,6 @@
 	l1_compt = L1_EEP_PIMM( component & COMPT_MASK );
 	break;
 
-      case C_DIMM:
-	/* one of the DIMMs */
-	l1_compt = L1_EEP_DIMM( component & COMPT_MASK );
-	r = read_spd( scp, subch, l1_compt, buf->spd );
-	sc_close( scp, subch );
-	return r;
-
       default:
 	/* unsupported board type */
 	sc_close( scp, subch );
@@ -1297,8 +1314,7 @@
 	scp = get_l1sc();
     }
     else {
-	elsc_t *get_elsc(void);
-	scp = get_elsc();
+	scp = &NODEPDA( NASID_TO_COMPACT_NODEID(nasid) )->module->elsc;
     }
 
     return _cbrick_eeprom_read( buf, scp, component );
@@ -1333,8 +1349,7 @@
 	scp = get_l1sc();
     }
     else {
-	elsc_t *get_elsc(void);
-	scp = get_elsc();
+	scp = &NODEPDA( NASID_TO_COMPACT_NODEID(nasid) )->module->elsc;
     }
 
     if( (subch = sc_open( scp, L1_ADDR_LOCALIO )) < 0 )
@@ -1350,9 +1365,11 @@
 
 	if( r != EEP_OK ) {
 	    sc_close( scp, subch );
-#ifdef BRINGUP /* Once EEPROMs are universally available, remove this */
+	/*
+	 * Whenever we no longer need to test on hardware
+	 * that does not have EEPROMS, then this can be removed.
+	 */
 	    r = fake_an_eeprom_record( buf, component, rtc_time() );
-#endif /* BRINGUP */
 	    return r;
 	}
 	break;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/hcl.c linux/arch/ia64/sn/io/hcl.c
--- v2.4.3/linux/arch/ia64/sn/io/hcl.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/hcl.c	Thu Apr  5 12:51:47 2001
@@ -30,6 +30,7 @@
 #define HCL_TEMP_NAME_LEN 44 
 #define HCL_VERSION "1.0"
 devfs_handle_t hwgraph_root = NULL;
+devfs_handle_t linux_busnum = NULL;
 
 /*
  * Debug flag definition.
@@ -41,7 +42,9 @@
 static unsigned int hcl_debug_init __initdata = HCL_DEBUG_NONE;
 #endif
 static unsigned int hcl_debug = HCL_DEBUG_NONE;
+#if defined(CONFIG_HCL_DEBUG) && !defined(MODULE)
 static unsigned int boot_options = OPTION_NONE;
+#endif
 
 /*
  * Some Global definitions.
@@ -49,6 +52,12 @@
 spinlock_t hcl_spinlock;
 devfs_handle_t hcl_handle = NULL;
 
+invplace_t invplace_none = {
+	GRAPH_VERTEX_NONE,
+	GRAPH_VERTEX_PLACE_NONE,
+	NULL
+};
+
 /*
  * HCL device driver.
  * The purpose of this device driver is to provide a facility 
@@ -98,6 +107,7 @@
 }
 
 struct file_operations hcl_fops = {
+	(struct module *)0,
 	NULL,		/* lseek - default */
 	NULL,		/* read - general block-dev read */
 	NULL,		/* write - general block-dev write */
@@ -110,9 +120,9 @@
 	hcl_close,	/* release */
 	NULL,		/* fsync */
 	NULL,		/* fasync */
-	NULL,		/* check_media_change */
-	NULL,		/* revalidate */
-	NULL		/* lock */
+	NULL,		/* lock */
+	NULL,		/* readv */
+	NULL,		/* writev */
 };
 
 
@@ -134,13 +144,15 @@
 	extern struct string_table label_string_table;
 	int rv = 0;
 
+#if defined(CONFIG_HCL_DEBUG) && !defined(MODULE)
 	printk ("\n%s: v%s Colin Ngam (cngam@sgi.com)\n",
 		HCL_NAME, HCL_VERSION);
-#if defined(CONFIG_HCL_DEBUG) && !defined(MODULE)
+
 	hcl_debug = hcl_debug_init;
 	printk ("%s: hcl_debug: 0x%0x\n", HCL_NAME, hcl_debug);
-#endif
 	printk ("\n%s: boot_options: 0x%0x\n", HCL_NAME, boot_options);
+#endif
+
 	spin_lock_init(&hcl_spinlock);
 
 	/*
@@ -148,7 +160,7 @@
 	 */
 	rv = hwgraph_path_add(NULL, "hw", &hwgraph_root);
 	if (rv)
-		printk ("init_hcl: Failed to create hwgraph_root. Error = %d.\n", rv);
+		printk ("WARNING: init_hcl: Failed to create hwgraph_root. Error = %d.\n", rv);
 
 	/*
 	 * Create the hcl driver to support inventory entry manipulations.
@@ -171,6 +183,15 @@
 	 */
 	string_table_init(&label_string_table);
 
+	/*
+	 * Create the directory that links Linux bus numbers to our Xwidget.
+	 */
+	rv = hwgraph_path_add(hwgraph_root, "linux/busnum", &linux_busnum);
+	if (linux_busnum == NULL) {
+		panic("HCL: Unable to create hw/linux/busnum\n");
+		return(0);
+	}
+
 	return(0);
 
 }
@@ -190,7 +211,6 @@
 {
     while ( (*str != '\0') && !isspace (*str) )
     {
-	printk("HCL: Boot time parameter %s\n", str);
 #ifdef CONFIG_HCL_DEBUG
         if (strncmp (str, "all", 3) == 0) {
             hcl_debug_init |= HCL_DEBUG_ALL;
@@ -445,7 +465,7 @@
 		/*
 		 * We need to clean up!
 		 */
-		printk("HCL: Unable to set the connect point to it's parent 0x%p\n",
+		printk(KERN_WARNING "HCL: Unable to set the connect point to it's parent 0x%p\n",
 			new_devfs_handle);
 	}
 
@@ -561,19 +581,44 @@
 {
 
 	char *path;
+	char *s1;
+	char *index;
 	int name_start;
 	devfs_handle_t handle = NULL;
 	int rv;
+	int i, count;
 
 	path = kmalloc(1024, GFP_KERNEL);
+	memset(path, 0x0, 1024);
+	name_start = devfs_generate_path (from, path, 1024);
+	s1 = &path[name_start];
+	count = 0;
+	while (1) {
+		index = strstr (s1, "/");
+		if (index) {
+			count++;
+			s1 = ++index;
+		} else {
+			count++;
+			break;
+		}
+	}
+
+	memset(path, 0x0, 1024);
 	name_start = devfs_generate_path (to, path, 1024);
 
+	for (i = 0; i < count; i++) {
+		strcat(path,"../");
+	}
+
+	strcat(path, &path[name_start]);
+
 	/*
 	 * Otherwise, just create a symlink to the vertex.
 	 * In this case the vertex was previous created with a REAL pathname.
 	 */
 	rv = devfs_mk_symlink (from, (const char *)name, 
-			       DEVFS_FL_DEFAULT, (const char *)&path[name_start],
+			       DEVFS_FL_DEFAULT, path,
 			       &handle, NULL);
 
 	name_start = devfs_generate_path (handle, path, 1024);
@@ -744,7 +789,6 @@
 		*placeptr = which_place + 1;
 		if (curr && name) {
 			tempname = devfs_get_name(*target, &namelen);
-			printk("hwgraph_edge_get_next: Component name = %s, length = %d\n", tempname, namelen);
 			if (tempname && namelen)
 				strcpy(name, tempname);
 		}
@@ -1335,7 +1379,7 @@
 		return(DEVNAME_UNKNOWN);
 }
 
-#ifdef IRIX
+#ifdef LATER
 /*
 ** Return the compact node id of the node that ultimately "owns" the specified
 ** vertex.  In order to do this, we walk back through masters and connect points
@@ -1440,7 +1484,7 @@
 
   return (mem_vhdl);
 }
-#endif /* IRIX */
+#endif /* LATER */
 
 
 /*
@@ -1454,7 +1498,7 @@
 {
 	devfs_handle_t xx = NULL;
 
-	printk("FIXME: hwgraph_char_device_add() called. Use hwgraph_register.\n");
+	printk("WARNING: hwgraph_char_device_add() not supported .. use hwgraph_register.\n");
 	*devhdl = xx;	// Must set devhdl
 	return(GRAPH_SUCCESS);
 }
@@ -1462,14 +1506,13 @@
 graph_error_t
 hwgraph_edge_remove(devfs_handle_t from, char *name, devfs_handle_t *toptr)
 {
-	printk("FIXME: hwgraph_edge_remove\n");
+	printk("WARNING: hwgraph_edge_remove NOT supported.\n");
 	return(GRAPH_ILLEGAL_REQUEST);
 }
 
 graph_error_t
 hwgraph_vertex_unref(devfs_handle_t vhdl)
 {
-	printk("FIXME: hwgraph_vertex_unref\n");
 	return(GRAPH_ILLEGAL_REQUEST);
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/hcl_util.c linux/arch/ia64/sn/io/hcl_util.c
--- v2.4.3/linux/arch/ia64/sn/io/hcl_util.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/hcl_util.c	Thu Apr  5 12:51:47 2001
@@ -137,6 +137,20 @@
 	}
 }
 
+/*
+** If the specified device represents a CPU, return its cpuid;
+** otherwise, return CPU_NONE.
+*/
+cpuid_t
+cpuvertex_to_cpuid(devfs_handle_t vhdl)
+{
+	arbitrary_info_t cpuid = CPU_NONE;
+
+	(void)labelcl_info_get_LBL(vhdl, INFO_LBL_CPUID, NULL, &cpuid);
+
+	return((cpuid_t)cpuid);
+}
+
 
 /*
 ** dev_to_name converts a devfs_handle_t into a canonical name.  If the devfs_handle_t
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/hubdev.c linux/arch/ia64/sn/io/hubdev.c
--- v2.4.3/linux/arch/ia64/sn/io/hubdev.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/hubdev.c	Thu Apr  5 12:51:47 2001
@@ -31,7 +31,7 @@
 void
 hubdev_init(void)
 {
-	mutex_init(&hubdev_callout_mutex, MUTEX_DEFAULT, "hubdev");
+	mutex_init(&hubdev_callout_mutex);
         hubdev_callout_list = NULL;
 }
         
@@ -45,9 +45,9 @@
         callout =  (hubdev_callout_t *)kmem_zalloc(sizeof(hubdev_callout_t), KM_SLEEP);
         ASSERT(callout);
         
-	mutex_lock(&hubdev_callout_mutex, PZERO);
+	mutex_lock(&hubdev_callout_mutex);
         /*
-         * Insert at the front of the list
+         * Insert at the end of the list
          */
         callout->fp = hubdev_callout_list;
         hubdev_callout_list = callout;
@@ -62,7 +62,7 @@
         
         ASSERT(attach_method);
    
-	mutex_lock(&hubdev_callout_mutex, PZERO);
+	mutex_lock(&hubdev_callout_mutex);
         /*
          * Remove registry element containing attach_method
          */
@@ -86,7 +86,7 @@
         hubdev_callout_t *p;
         int errcode;
 
-	mutex_lock(&hubdev_callout_mutex, PZERO);
+	mutex_lock(&hubdev_callout_mutex);
         
         for (p = hubdev_callout_list; p != NULL; p = p->fp) {
                 ASSERT(p->attach_method);
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/huberror.c linux/arch/ia64/sn/io/huberror.c
--- v2.4.3/linux/arch/ia64/sn/io/huberror.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/io/huberror.c	Thu Apr  5 12:51:47 2001
@@ -0,0 +1,475 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2000 by Alan Mayer
+ */
+
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/smp.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/nodemask.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/synergy.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/intr.h>
+
+extern void hubni_eint_init(cnodeid_t cnode);
+extern void hubii_eint_init(cnodeid_t cnode);
+extern void hubii_eint_handler (int irq, void *arg, struct pt_regs *ep);
+extern void snia_error_intr_handler(int irq, void *devid, struct pt_regs *pt_regs);
+
+extern int maxcpus;
+
+#define HUB_ERROR_PERIOD        (120 * HZ)      /* 2 minutes */
+
+
+void
+hub_error_clear(nasid_t nasid)
+{
+	int i;
+	hubreg_t idsr;
+	int sn;
+
+	for(sn=0; sn<NUM_SUBNODES; sn++) {
+		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_PEND, -1);
+		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_STATUS0_A_CLR, -1);
+		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_STATUS0_B_CLR, -1);
+		REMOTE_HUB_PI_S(nasid, sn, PI_SPURIOUS_HDR_0, 0);
+		REMOTE_HUB_PI_S(nasid, sn, PI_SPURIOUS_HDR_1, 0);
+	}
+
+	REMOTE_HUB_L(nasid, MD_DIR_ERROR_CLR);
+	REMOTE_HUB_L(nasid, MD_MEM_ERROR_CLR);
+	REMOTE_HUB_L(nasid, MD_MISC1_ERROR_CLR);
+	REMOTE_HUB_L(nasid, MD_PROTOCOL_ERR_CLR);
+
+    /*
+     * Make sure spurious write response errors are cleared
+     * (values are from hub_set_prb())
+     */
+    for (i = 0; i <= HUB_WIDGET_ID_MAX - HUB_WIDGET_ID_MIN + 1; i++) {
+        iprb_t prb;
+
+	prb.iprb_regval = REMOTE_HUB_L(nasid, IIO_IOPRB_0 + (i * sizeof(hubreg_t)));
+
+        /* Clear out some fields */
+        prb.iprb_ovflow = 1;
+        prb.iprb_bnakctr = 0;
+        prb.iprb_anakctr = 0;
+
+	/*
+	 * PIO reads in fire-and-forget mode on bedrock 1.0 don't
+	 * frob the credit count properly, making the responses appear
+	 * spurious.  So don't use fire-and-forget mode.  Bug 761802.
+	 */
+        prb.iprb_ff = 0;        /* disable fire-and-forget mode by default */
+
+        prb.iprb_xtalkctr = 3;  /* approx. PIO credits for the widget */
+
+        REMOTE_HUB_S(nasid, IIO_IOPRB_0 + (i * sizeof(hubreg_t)), prb.iprb_regval);
+    }
+
+    REMOTE_HUB_S(nasid, IIO_IO_ERR_CLR, -1);
+    idsr = REMOTE_HUB_L(nasid, IIO_IIDSR);
+    REMOTE_HUB_S(nasid, IIO_IIDSR, (idsr & ~(IIO_IIDSR_SENT_MASK)));
+
+    REMOTE_HUB_L(nasid, NI_PORT_ERROR_CLEAR);
+    /* No need to clear NI_PORT_HEADER regs; they are continually overwritten*/
+
+    REMOTE_HUB_S(nasid, LB_ERROR_MASK_CLR, -1);
+    REMOTE_HUB_S(nasid, LB_ERROR_HDR1, 0);
+
+    /* Clear XB error regs, in order */
+    for (i = 0;
+         i <= XB_FIRST_ERROR_CLEAR - XB_POQ0_ERROR_CLEAR;
+         i += sizeof(hubreg_t)) {
+        REMOTE_HUB_S(nasid, XB_POQ0_ERROR_CLEAR + i, 0);
+    }
+}
+
+
+/*
+ * Function	: hub_error_init
+ * Purpose	: initialize the error handling requirements for a given hub.
+ * Parameters	: cnode, the compact nodeid.
+ * Assumptions	: Called only once per hub, either by a local cpu. Or by a 
+ *			remote cpu, when this hub is headless.(cpuless)
+ * Returns	: None
+ */
+
+void
+hub_error_init(cnodeid_t cnode)
+{
+	nasid_t nasid;
+
+    nasid = cnodeid_to_nasid(cnode);
+    hub_error_clear(nasid);
+
+#ifdef ajm
+    if (cnode == 0) {
+	/*
+	 * Allocate log for storing the node specific error info
+	 */
+	for (i = 0; i < numnodes; i++) {
+	    kl_error_log[i]  = kmem_zalloc_node(sizeof(sn0_error_log_t), 
+						KM_NOSLEEP, i);
+	    hub_err_count[i] = kmem_zalloc_node(sizeof(hub_errcnt_t),
+						VM_DIRECT | KM_NOSLEEP, i);
+	    ASSERT_ALWAYS(kl_error_log[i] && hub_err_count[i]);
+	}
+    }
+
+    /*
+     * Assumption: There will be only one cpu who will initialize
+     * a hub. we need to setup the ii and each pi error interrupts.
+     * The SN1 hub (bedrock) has two PI, one for up to two processors.
+     */
+
+    if (cpuid_to_cnodeid(smp_processor_id()) == cnode) { 
+	int generic_intr_mask = PI_ERR_GENERIC; /* These interrupts are sent to only 1 CPU per NODE */
+
+	ASSERT_ALWAYS(kl_error_log[cnode]);
+	ASSERT_ALWAYS(hub_err_count[cnode]);
+	MD_ERR_LOG_INIT(kl_error_log[cnode]);
+
+	/* One for each CPU */
+	recover_error_init(RECOVER_ERROR_TABLE(cnode, 0));
+	recover_error_init(RECOVER_ERROR_TABLE(cnode, 1));
+	recover_error_init(RECOVER_ERROR_TABLE(cnode, 2));
+	recover_error_init(RECOVER_ERROR_TABLE(cnode, 3));
+
+	/*
+	 * Setup error intr masks.
+	 */
+	for(sn=0; sn<NUM_SUBNODES; sn++) {
+		int cpuA_present = REMOTE_HUB_PI_L(nasid, sn, PI_CPU_ENABLE_A);
+		int cpuB_present = REMOTE_HUB_PI_L(nasid, sn, PI_CPU_ENABLE_B);
+
+		if (cpuA_present) {
+			if (cpuB_present) {		/* A && B */
+	    			REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_MASK_A,
+					(PI_FATAL_ERR_CPU_B | PI_MISC_ERR_CPU_A|generic_intr_mask));
+	    			REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_MASK_B,
+					(PI_FATAL_ERR_CPU_A | PI_MISC_ERR_CPU_B));
+
+			} else {			/* A && !B */
+	    			REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_MASK_A,
+					(PI_FATAL_ERR_CPU_A | PI_MISC_ERR_CPU_A|generic_intr_mask));
+			}
+			generic_intr_mask = 0;
+		} else {
+			if (cpuB_present) {		/* !A && B */
+	    			REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_MASK_B,
+					(PI_FATAL_ERR_CPU_B | PI_MISC_ERR_CPU_B|generic_intr_mask));
+				generic_intr_mask = 0;
+
+			} else {			/* !A && !B */
+				/* nothing to set up */
+			}
+		}
+	}
+
+	/*
+	 * Turn off UNCAC_UNCORR interrupt in the masks. Anyone interested
+	 * in these errors will peek at the int pend register to see if its
+	 * set.
+	 */ 
+	for(sn=0; sn<NUM_SUBNODES; sn++) {
+		misc = REMOTE_HUB_PI_L(nasid, sn, PI_ERR_INT_MASK_A);
+		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_MASK_A, (misc & ~PI_ERR_UNCAC_UNCORR_A));
+		misc = REMOTE_HUB_PI_L(nasid, sn, PI_ERR_INT_MASK_B);
+		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_MASK_B, (misc & ~PI_ERR_UNCAC_UNCORR_B));
+	}
+
+	/*
+	 * enable all error indicators to turn on, in case of errors.
+	 *
+	 * This is not good on single cpu node boards.
+	 **** LOCAL_HUB_S(PI_SYSAD_ERRCHK_EN, PI_SYSAD_CHECK_ALL);
+	 */
+	for(sn=0; sn<NUM_SUBNODES; sn++) {
+		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_STATUS1_A_CLR, 0);
+		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_STATUS1_B_CLR, 0);
+	}
+
+	/* Set up stack for each present processor */
+	for(sn=0; sn<NUM_SUBNODES; sn++) {
+		if (REMOTE_HUB_PI_L(nasid, sn, PI_CPU_PRESENT_A)) {
+	    	SN0_ERROR_LOG(cnode)->el_spool_cur_addr[0] =
+			SN0_ERROR_LOG(cnode)->el_spool_last_addr[0] =
+		    	REMOTE_HUB_PI_L(nasid, sn, PI_ERR_STACK_ADDR_A);
+		}
+	    
+		if (REMOTE_HUB_PI_L(nasid, sn, PI_CPU_PRESENT_B)) {
+	    	SN0_ERROR_LOG(cnode)->el_spool_cur_addr[1] =
+			SN0_ERROR_LOG(cnode)->el_spool_last_addr[1] =
+		    	REMOTE_HUB_PI_L(nasid, sn, PI_ERR_STACK_ADDR_B);
+		}
+	}
+
+
+	PI_SPOOL_SIZE_BYTES = 
+	    ERR_STACK_SIZE_BYTES(REMOTE_HUB_L(nasid, PI_ERR_STACK_SIZE));
+
+#ifdef BRINGUP
+/* BRINGUP: The following code looks like a check to make sure
+the prom set up the error spool correctly for 2 processors.  I
+don't think it is needed.  */
+	for(sn=0; sn<NUM_SUBNODES; sn++) {
+		if (REMOTE_HUB_PI_L(nasid, sn, PI_CPU_PRESENT_B)) {
+			__psunsigned_t addr_a = REMOTE_HUB_PI_L(nasid, sn, PI_ERR_STACK_ADDR_A);
+			__psunsigned_t addr_b = REMOTE_HUB_PI_L(nasid, sn, PI_ERR_STACK_ADDR_B);
+			if ((addr_a & ~0xff) == (addr_b & ~0xff)) {
+			    REMOTE_HUB_PI_S(nasid, sn, PI_ERR_STACK_ADDR_B, 	
+					addr_b + PI_SPOOL_SIZE_BYTES);
+	
+			    SN0_ERROR_LOG(cnode)->el_spool_cur_addr[1] =
+				SN0_ERROR_LOG(cnode)->el_spool_last_addr[1] =
+				    REMOTE_HUB_PI_L(nasid, sn, PI_ERR_STACK_ADDR_B);
+	
+		    }
+		}
+	}
+#endif /* BRINGUP */
+
+	/* programming our own hub. Enable error_int_pend intr.
+	 * If both present, CPU A takes CPU b's error interrupts and any
+	 * generic ones. CPU B takes CPU A error ints.
+	 */
+	if (cause_intr_connect (SRB_ERR_IDX,
+				(intr_func_t)(hubpi_eint_handler),
+				SR_ALL_MASK|SR_IE)) {
+	    cmn_err(ERR_WARN, 
+		    "hub_error_init: cause_intr_connect failed on %d", cnode);
+	}
+    }
+    else {
+	/* programming remote hub. The only valid reason that this
+	 * is called will be on headless hubs. No interrupts 
+	 */
+	for(sn=0; sn<NUM_SUBNODES; sn++) {
+		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_MASK_A, 0); /* not necessary */
+		REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_MASK_B, 0); /* not necessary */
+	}
+    }
+#endif /* ajm */
+    /*
+     * Now setup the hub ii and ni error interrupt handler.
+     */
+
+    hubii_eint_init(cnode);
+    hubni_eint_init(cnode);
+
+#ifdef ajm
+    /*** XXX FIXME XXX resolve the following***/
+    /* INT_PEND1 bits set up for one hub only:
+     *	SHUTDOWN_INTR
+     *	MD_COR_ERR_INTR
+     *  COR_ERR_INTR_A and COR_ERR_INTR_B should be sent to the
+     *  appropriate CPU only.
+     */
+
+    if (cnode == 0) {
+	    error_consistency_check.eps_state = 0;
+	    error_consistency_check.eps_cpuid = -1;
+	    spinlock_init(&error_consistency_check.eps_lock, "error_dump_lock");
+    }
+#endif
+
+    nodepda->huberror_ticks = HUB_ERROR_PERIOD;
+    return;
+}
+
+/*
+ * Function	: hubii_eint_init
+ * Parameters	: cnode
+ * Purpose	: to initialize the hub iio error interrupt.
+ * Assumptions	: Called once per hub, by the cpu which will ultimately
+ *			handle this interrupt.
+ * Returns	: None.
+ */
+
+
+void
+hubii_eint_init(cnodeid_t cnode)
+{
+    int			bit, rv;
+    ii_iidsr_u_t    	hubio_eint;
+    hubinfo_t		hinfo; 
+    cpuid_t		intr_cpu;
+    devfs_handle_t 	hub_v;
+    ii_ilcsr_u_t	ilcsr;
+
+    hub_v = (devfs_handle_t)cnodeid_to_vertex(cnode);
+    ASSERT_ALWAYS(hub_v);
+    hubinfo_get(hub_v, &hinfo);
+
+    ASSERT(hinfo);
+    ASSERT(hinfo->h_cnodeid == cnode);
+
+    ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_ILCSR);
+
+    if ((ilcsr.ii_ilcsr_fld_s.i_llp_stat & 0x2) == 0) {
+	/* 
+	 * HUB II link is not up. 
+	 * Just disable LLP, and don't connect any interrupts.
+	 */
+	ilcsr.ii_ilcsr_fld_s.i_llp_en = 0;
+	REMOTE_HUB_S(hinfo->h_nasid, IIO_ILCSR, ilcsr.ii_ilcsr_regval);
+	return;
+    }
+    /* Select a possible interrupt target where there is a free interrupt
+     * bit and also reserve the interrupt bit for this IO error interrupt
+     */
+    intr_cpu = intr_heuristic(hub_v,0,INTRCONNECT_ANYBIT,II_ERRORINT,hub_v,
+			      "HUB IO error interrupt",&bit);
+    if (intr_cpu == CPU_NONE) {
+	printk("hubii_eint_init: intr_reserve_level failed, cnode %d", cnode);
+	return;
+    }
+	
+    rv = intr_connect_level(intr_cpu, bit, 0,(intr_func_t)(NULL),
+			    (void *)(long)hub_v, NULL);
+    synergy_intr_connect(bit, intr_cpu);
+    request_irq(bit_pos_to_irq(bit) + (intr_cpu << 8), hubii_eint_handler, 0, NULL, (void *)hub_v);
+    ASSERT_ALWAYS(rv >= 0);
+    hubio_eint.ii_iidsr_regval = 0;
+    hubio_eint.ii_iidsr_fld_s.i_enable = 1;
+    hubio_eint.ii_iidsr_fld_s.i_level = bit;/* Take the least significant bits*/
+    hubio_eint.ii_iidsr_fld_s.i_node = COMPACT_TO_NASID_NODEID(cnode);
+    hubio_eint.ii_iidsr_fld_s.i_pi_id = cpuid_to_subnode(intr_cpu);
+    REMOTE_HUB_S(hinfo->h_nasid, IIO_IIDSR, hubio_eint.ii_iidsr_regval);
+
+}
+
+void
+hubni_eint_init(cnodeid_t cnode)
+{
+    int intr_bit;
+    cpuid_t targ;
+
+
+    if ((targ = cnodeid_to_cpuid(cnode)) == CPU_NONE)
+	return;
+
+	/* The prom chooses which cpu gets these interrupts, but we
+	*  don't know which one it chose.  We will register all of the 
+	*  cpus to be sure.  This only costs us an irqaction per cpu.
+	*/
+    for (; targ < CPUS_PER_NODE; targ++) {
+	if (!cpu_enabled(targ) ) continue;
+	/* connect the INTEND1 bits. */
+	for (intr_bit = XB_ERROR; intr_bit <= MSC_PANIC_INTR; intr_bit++) {
+		intr_connect_level(targ, intr_bit, II_ERRORINT, NULL, NULL, NULL);
+	}
+	request_irq(SGI_HUB_ERROR_IRQ + (targ << 8), snia_error_intr_handler, 0, NULL, NULL);
+	/* synergy masks are initialized in the prom to enable all interrupts. */
+	/* We'll just leave them that way, here, for these interrupts. */
+    }
+}
+
+
+/*ARGSUSED*/
+void
+hubii_eint_handler (int irq, void *arg, struct pt_regs *ep)
+{
+    devfs_handle_t	hub_v;
+    hubinfo_t		hinfo; 
+    ii_wstat_u_t	wstat;
+    hubreg_t		idsr;
+
+	panic("Hubii interrupt\n");
+#ifdef ajm
+    /*
+     * If the NI has a problem, everyone has a problem.  We shouldn't
+     * even attempt to handle other errors when an NI error is present.
+     */
+    if (check_ni_errors()) {
+	hubni_error_handler("II interrupt", 1);
+	/* NOTREACHED */
+    }
+
+    /* two levels of casting avoids compiler warning.!! */
+    hub_v = (devfs_handle_t)(long)(arg); 
+    ASSERT(hub_v);
+
+    hubinfo_get(hub_v, &hinfo);
+    
+    /* 
+     * Identify the reason for error. 
+     */
+    wstat.ii_wstat_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_WSTAT);
+
+    if (wstat.ii_wstat_fld_s.w_crazy) {
+	char	*reason;
+	/*
+	 * We can do a couple of things here. 
+	 * Look at the fields TX_MX_RTY/XT_TAIL_TO/XT_CRD_TO to check
+	 * which of these caused the CRAZY bit to be set. 
+	 * You may be able to check if the Link is up really.
+	 */
+	if (wstat.ii_wstat_fld_s.w_tx_mx_rty)
+		reason = "Micro Packet Retry Timeout";
+	else if (wstat.ii_wstat_fld_s.w_xt_tail_to)
+		reason = "Crosstalk Tail Timeout";
+	else if (wstat.ii_wstat_fld_s.w_xt_crd_to)
+		reason = "Crosstalk Credit Timeout";
+	else {
+		hubreg_t	hubii_imem;
+		/*
+		 * Check if widget 0 has been marked as shutdown, or
+		 * if BTE 0/1 has been marked.
+		 */
+		hubii_imem = REMOTE_HUB_L(hinfo->h_nasid, IIO_IMEM);
+		if (hubii_imem & IIO_IMEM_W0ESD)
+			reason = "Hub Widget 0 has been Shutdown";
+		else if (hubii_imem & IIO_IMEM_B0ESD)
+			reason = "BTE 0 has been shutdown";
+		else if (hubii_imem & IIO_IMEM_B1ESD)
+			reason = "BTE 1 has been shutdown";
+		else	reason = "Unknown";
+	
+	}
+	/*
+	 * Note: we may never be able to print this, if the II talking
+	 * to Xbow which hosts the console is dead. 
+	 */
+	printk("Hub %d to Xtalk Link failed (II_ECRAZY) Reason: %s", 
+		hinfo->h_cnodeid, reason);
+    }
+
+    /* 
+     * It's a toss as to which one among PRB/CRB to check first. 
+     * Current decision is based on the severity of the errors. 
+     * IO CRB errors tend to be more severe than PRB errors.
+     *
+     * It is possible for BTE errors to have been handled already, so we
+     * may not see any errors handled here. 
+     */
+    (void)hubiio_crb_error_handler(hub_v, hinfo);
+    (void)hubiio_prb_error_handler(hub_v, hinfo);
+    /*
+     * If we reach here, it indicates crb/prb handlers successfully
+     * handled the error. So, re-enable II to send more interrupt
+     * and return.
+     */
+    REMOTE_HUB_S(hinfo->h_nasid, IIO_IECLR, 0xffffff);
+    idsr = REMOTE_HUB_L(hinfo->h_nasid, IIO_IIDSR) & ~IIO_IIDSR_SENT_MASK;
+    REMOTE_HUB_S(hinfo->h_nasid, IIO_IIDSR, idsr);
+#endif /* ajm */
+}
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/hubspc.c linux/arch/ia64/sn/io/hubspc.c
--- v2.4.3/linux/arch/ia64/sn/io/hubspc.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/hubspc.c	Thu Apr  5 12:51:47 2001
@@ -61,7 +61,7 @@
 }cpuprom_info_t;
 
 static cpuprom_info_t	*cpuprom_head;
-lock_t	cpuprom_spinlock;
+spinlock_t	cpuprom_spinlock;
 #define	PROM_LOCK()	mutex_spinlock(&cpuprom_spinlock)
 #define	PROM_UNLOCK(s)	mutex_spinunlock(&cpuprom_spinlock, (s))
 
@@ -72,7 +72,7 @@
 prominfo_add(devfs_handle_t hub, devfs_handle_t prom)
 {
 	cpuprom_info_t	*info;
-	int	s;
+	unsigned long	s;
 
 	info = kmalloc(sizeof(cpuprom_info_t), GFP_KERNEL);
 	ASSERT(info);
@@ -89,7 +89,7 @@
 void
 prominfo_del(devfs_handle_t prom)
 {
-	int	s;
+	unsigned long	s;
 	cpuprom_info_t	*info;
 	cpuprom_info_t	**prev;
 
@@ -111,7 +111,7 @@
 devfs_handle_t
 prominfo_nodeget(devfs_handle_t prom)
 {
-	int	s;
+	unsigned long	s;
 	cpuprom_info_t	*info;
 
 	s = PROM_LOCK();
@@ -297,7 +297,7 @@
 	printf("hubspc_init: Completed\n");
 #endif	/* HUBSPC_DEBUG */
 	/* Initialize spinlocks */
-	spinlock_init(&cpuprom_spinlock, "promlist");
+	mutex_spinlock_init(&cpuprom_spinlock);
 }
 
 /* ARGSUSED */
@@ -312,12 +312,6 @@
                 break;
 
         case HUBSPC_PROM:
-		/* Check if the user has proper access rights to 
-		 * read/write the prom space.
-		 */
-                if (!cap_able(CAP_DEVICE_MGT)) {
-                        errcode = EPERM;
-                }                
                 break;
 
         default:
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/invent.c linux/arch/ia64/sn/io/invent.c
--- v2.4.3/linux/arch/ia64/sn/io/invent.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/invent.c	Thu Apr  5 12:51:47 2001
@@ -61,6 +61,9 @@
  * These two routines are intended to prevent the caller from having to know
  * the internal structure of the inventory table.
  *
+ * The caller of get_next_inventory is supposed to call start_scan_invent
+ * before the irst call to get_next_inventory, and the caller is required
+ * to call end_scan_invent after the last call to get_next_inventory.
  */
 inventory_t *
 get_next_inventory(invplace_t *place)
@@ -74,11 +77,15 @@
 		 * We've exhausted inventory items on the last device.
 		 * Advance to next device.
 		 */
+		place->invplace_inv = NULL; /* Start from beginning invent on this device */
 		rv = hwgraph_vertex_get_next(&device, &place->invplace_vplace);
-		if (rv != LABELCL_SUCCESS)
+		if (rv == LABELCL_SUCCESS) {
+			place->invplace_vhdl = device;
+		}
+		else {
+			place->invplace_vhdl = GRAPH_VERTEX_NONE;
 			return(NULL);
-		place->invplace_vhdl = device;
-		place->invplace_inv = NULL; /* Start from beginning invent on this device */
+		}
 	}
 
 	return(pinv);
@@ -91,6 +98,23 @@
 	return sizeof(inventory_t);
 }
 
+/* Must be called prior to first call to get_next_inventory */
+void
+start_scan_inventory(invplace_t *iplace)
+{
+	*iplace = INVPLACE_NONE;
+}
+
+/* Must be called after last call to get_next_inventory */
+void
+end_scan_inventory(invplace_t *iplace)
+{
+	devfs_handle_t vhdl = iplace->invplace_vhdl;
+	if (vhdl != GRAPH_VERTEX_NONE)
+		hwgraph_vertex_unref(vhdl);
+	*iplace = INVPLACE_NONE; /* paranoia */
+}
+
 /*
  * Hardware inventory scanner.
  *
@@ -106,11 +130,13 @@
 
 	ie = 0;
 	rc = 0;
-	while ( (ie = (inventory_t *)get_next_inventory(&iplace)) ) {
+	start_scan_inventory(&iplace);
+	while ((ie = (inventory_t *)get_next_inventory(&iplace))) {
 		rc = (*fun)(ie, arg);
 		if (rc)
 			break;
 	}
+	end_scan_inventory(&iplace);
 	return rc;
 }
 
@@ -127,6 +153,7 @@
 {
 	invplace_t iplace =  { NULL,NULL, NULL };
 
+	start_scan_inventory(&iplace);
 	while ((pinv = (inventory_t *)get_next_inventory(&iplace)) != NULL) {
 		if (class != -1 && pinv->inv_class != class)
 			continue;
@@ -146,6 +173,7 @@
 			continue;
 		break;
 	}
+	end_scan_inventory(&iplace);
 
 	return(pinv);
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/io.c linux/arch/ia64/sn/io/io.c
--- v2.4.3/linux/arch/ia64/sn/io/io.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/io.c	Thu Apr 12 12:16:35 2001
@@ -13,7 +13,6 @@
 #include <linux/slab.h>
 #include <asm/sn/types.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/cmn_err.h>
 #include <asm/sn/iobus.h>
 #include <asm/sn/iograph.h>
 #include <asm/param.h>
@@ -33,11 +32,6 @@
 
 extern xtalk_provider_t hub_provider;
 
-#ifndef CONFIG_IA64_SGI_IO
-/* Global variables */
-extern pdaindr_t       pdaindr[MAXCPUS];
-#endif
-
 /*
  * Perform any initializations needed to support hub-based I/O.
  * Called once during startup.
@@ -45,7 +39,7 @@
 void
 hubio_init(void)
 {
-#if 0
+#ifdef	LATER
 	/* This isn't needed unless we port the entire sio driver ... */
         extern void early_brl1_port_init( void );
 	early_brl1_port_init();
@@ -101,17 +95,14 @@
 		hub_piomap->hpio_flags = HUB_PIOMAP_IS_BIGWINDOW;
 		IIO_ITTE_DISABLE(nasid, bigwin);
 	}
-#ifdef	BRINGUP
 	hub_set_piomode(nasid, HUB_PIO_CONVEYOR);
-#else
-	/* Set all the xwidgets in fire-and-forget mode
-	 * by default
-	 */
-	hub_set_piomode(nasid, HUB_PIO_FIRE_N_FORGET);
-#endif	/* BRINGUP */
 
-	sv_init(&hubinfo->h_bwwait, SV_FIFO, "bigwin");
-	spinlock_init(&hubinfo->h_bwlock, "bigwin");
+	mutex_spinlock_init(&hubinfo->h_bwlock);
+/*
+ * If this lock can be acquired from interrupts or bh's, add SV_INTS or SV_BHS,
+ * respectively, to the flags here.
+ */
+	sv_init(&hubinfo->h_bwwait, &hubinfo->h_bwlock, SV_ORDER_FIFO | SV_MON_SPIN); 
 }
 
 /* 
@@ -143,7 +134,7 @@
 	int bigwin, free_bw_index;
 	nasid_t nasid;
 	volatile hubreg_t junk;
-	int s;
+	unsigned long s;
 
 	/* sanity check */
 	if (byte_count_max > byte_count)
@@ -222,7 +213,7 @@
 				goto done;
 			}
 
-			sv_wait(&hubinfo->h_bwwait, PZERO, &hubinfo->h_bwlock, s);
+			sv_wait(&hubinfo->h_bwwait, 0, 0);
 			goto tryagain;
 		}
 	}
@@ -282,7 +273,7 @@
 	devfs_handle_t hubv;
 	hubinfo_t hubinfo;
 	nasid_t nasid;
-	int s;
+	unsigned long s;
 
 	/* 
 	 * Small windows are permanently mapped to corresponding widgets,
@@ -463,9 +454,9 @@
 	    if (!(dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
 		vhdl = dmamap->hdma_xtalk_info.xd_dev;
 #if defined(SUPPORT_PRINTING_V_FORMAT)
-		cmn_err(CE_WARN, "%v: hub_dmamap_addr re-uses dmamap.\n",vhdl);
+		PRINT_WARNING("%v: hub_dmamap_addr re-uses dmamap.\n",vhdl);
 #else
-		cmn_err(CE_WARN, "0x%p: hub_dmamap_addr re-uses dmamap.\n", &vhdl);
+		PRINT_WARNING("0x%x: hub_dmamap_addr re-uses dmamap.\n", vhdl);
 #endif
 	    }
 	} else {
@@ -496,9 +487,9 @@
 	    if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
 		vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
 #if defined(SUPPORT_PRINTING_V_FORMAT)
-		cmn_err(CE_WARN,"%v: hub_dmamap_list re-uses dmamap\n",vhdl);
+		PRINT_WARNING("%v: hub_dmamap_list re-uses dmamap\n",vhdl);
 #else
-		cmn_err(CE_WARN,"0x%p: hub_dmamap_list re-uses dmamap\n", &vhdl);
+		PRINT_WARNING("0x%x: hub_dmamap_list re-uses dmamap\n", vhdl);
 #endif
 	    }
 	} else {
@@ -525,9 +516,9 @@
 	    if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
 		vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
 #if defined(SUPPORT_PRINTING_V_FORMAT)
-		cmn_err(CE_WARN, "%v: hub_dmamap_done already done with dmamap\n",vhdl);
+		PRINT_WARNING("%v: hub_dmamap_done already done with dmamap\n",vhdl);
 #else
-		cmn_err(CE_WARN, "0x%p: hub_dmamap_done already done with dmamap\n", &vhdl);
+		PRINT_WARNING("0x%x: hub_dmamap_done already done with dmamap\n", vhdl);
 #endif
 	    }
 	}
@@ -629,16 +620,17 @@
  * Allocate resources required for an interrupt as specified in dev_desc.
  * Returns a hub interrupt handle on success, or 0 on failure.
  */
-hub_intr_t
-hub_intr_alloc(	devfs_handle_t dev,		/* which crosstalk device */
-		device_desc_t dev_desc,		/* device descriptor */
-		devfs_handle_t owner_dev)		/* owner of this interrupt, if known */
+static hub_intr_t
+do_hub_intr_alloc(devfs_handle_t dev,		/* which crosstalk device */
+		  device_desc_t dev_desc,	/* device descriptor */
+		  devfs_handle_t owner_dev,	/* owner of this interrupt, if known */
+		  int uncond_nothread)		/* unconditionally non-threaded */
 {
-	cpuid_t cpu;			/* cpu to receive interrupt */
+	cpuid_t cpu = (cpuid_t)0;			/* cpu to receive interrupt */
         int cpupicked = 0;
 	int bit;			/* interrupt vector */
 	/*REFERENCED*/
-	int intr_resflags;
+	int intr_resflags = 0;
 	hub_intr_t intr_hdl;
 	cnodeid_t nodeid;		/* node to receive interrupt */
 	/*REFERENCED*/
@@ -665,7 +657,7 @@
 		intr_swlevel = device_desc_intr_swlevel_get(dev_desc);
 		if (dev_desc->flags & D_INTR_ISERR) {
 			intr_resflags = II_ERRORINT;
-		} else if (!(dev_desc->flags & D_INTR_NOTHREAD)) {
+		} else if (!uncond_nothread && !(dev_desc->flags & D_INTR_NOTHREAD)) {
 			intr_resflags = II_THREADED;
 		} else {
 			/* Neither an error nor a thread. */
@@ -673,7 +665,8 @@
 		}
 	} else {
 		intr_swlevel = default_intr_pri;
-		intr_resflags = II_THREADED;
+		if (!uncond_nothread)
+			intr_resflags = II_THREADED;
 	}
 
 	/* XXX - Need to determine if the interrupt should be threaded. */
@@ -692,13 +685,11 @@
 	/* At this point we SHOULD have a valid cpu */
 	if (cpu == CPU_NONE) {
 #if defined(SUPPORT_PRINTING_V_FORMAT)
-		cmn_err(CE_WARN, 
-			"%v hub_intr_alloc could not allocate interrupt\n",
+		PRINT_WARNING("%v hub_intr_alloc could not allocate interrupt\n",
 			owner_dev);
 #else
-		cmn_err(CE_WARN, 
-			"0x%p hub_intr_alloc could not allocate interrupt\n",
-			&owner_dev);
+		PRINT_WARNING("0x%x hub_intr_alloc could not allocate interrupt\n",
+			owner_dev);
 #endif
 		return(0);
 
@@ -714,15 +705,13 @@
 					 owner_dev, intr_name);
 		if (bit < 0) {
 #if defined(SUPPORT_PRINTING_V_FORMAT)
-			cmn_err(CE_WARN,
-				"Could not reserve an interrupt bit for cpu "
+			PRINT_WARNING("Could not reserve an interrupt bit for cpu "
 				" %d and dev %v\n",
 				cpu,owner_dev);
 #else
-			cmn_err(CE_WARN,
-				"Could not reserve an interrupt bit for cpu "
+			PRINT_WARNING("Could not reserve an interrupt bit for cpu "
 				" %d and dev 0x%x\n",
-				cpu, &owner_dev);
+				cpu, owner_dev);
 #endif
 				
 			return(0);
@@ -751,8 +740,6 @@
 	xtalk_info->xi_dev = dev;
 	xtalk_info->xi_vector = bit;
 	xtalk_info->xi_addr = xtalk_addr;
-	xtalk_info->xi_flags =  (intr_resflags == II_THREADED) ?
-				0 : XTALK_INTR_NOTHREAD;
 
 	/*
 	 * Regardless of which CPU we ultimately interrupt, a given crosstalk
@@ -779,6 +766,31 @@
 	return(intr_hdl);
 }
 
+/*
+ * Allocate resources required for an interrupt as specified in dev_desc.
+ * Returns a hub interrupt handle on success, or 0 on failure.
+ */
+hub_intr_t
+hub_intr_alloc(	devfs_handle_t dev,		/* which crosstalk device */
+		device_desc_t dev_desc,		/* device descriptor */
+		devfs_handle_t owner_dev)		/* owner of this interrupt, if known */
+{
+	return(do_hub_intr_alloc(dev, dev_desc, owner_dev, 0));
+}
+
+/*
+ * Allocate resources required for an interrupt as specified in dev_desc.
+ * Uncondtionally request non-threaded, regardless of what the device
+ * descriptor might say.
+ * Returns a hub interrupt handle on success, or 0 on failure.
+ */
+hub_intr_t
+hub_intr_alloc_nothd(devfs_handle_t dev,		/* which crosstalk device */
+		device_desc_t dev_desc,		/* device descriptor */
+		devfs_handle_t owner_dev)		/* owner of this interrupt, if known */
+{
+	return(do_hub_intr_alloc(dev, dev_desc, owner_dev, 1));
+}
 
 /*
  * Free resources consumed by intr_alloc.
@@ -1001,7 +1013,7 @@
 {
 	iprb_t prb;
 	int prb_offset;
-#ifdef IRIX
+#ifdef LATER
 	extern int force_fire_and_forget;
 	extern volatile int ignore_conveyor_override;
 
@@ -1063,7 +1075,7 @@
 	int direct_connect;
 	hubii_wcr_t ii_wcr;
 	int prbnum;
-	int s, cons_lock = 0;
+	int cons_lock = 0;
 
 	ASSERT(NASID_TO_COMPACT_NODEID(nasid) != INVALID_CNODEID);
 	if (nasid == get_console_nasid()) {
@@ -1098,15 +1110,6 @@
 		hub_setup_prb(nasid, prbnum, 3, conveyor);
 	}
 
-#ifdef IRIX
-	/*
-	 * In direct connect mode, disable access to all widgets but 0.
-	 * Later, the prom will do this for us.
-	 */
-	if (direct_connect)
-		ii_iowa = 1;
-#endif
-
 	REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
 
 	if (cons_lock)
@@ -1151,7 +1154,8 @@
 	devfs_handle_t		hub_vhdl    = xwidget_info_master_get(widget_info);
 	hubinfo_t		hub_info = 0;
 	nasid_t			nasid;
-	int			s,rv;
+	unsigned long		s;
+	int			rv;
 
 	/* Use the nasid from the hub info hanging off the hub vertex
 	 * and widget number from the widget vertex
@@ -1178,7 +1182,7 @@
 	devfs_handle_t		hub_vhdl    = xwidget_info_master_get(widget_info);
 	hubinfo_t		hub_info = 0;
 	nasid_t			nasid;
-	int			s;
+	unsigned long			s;
 
 	/* Use the nasid from the hub info hanging off the hub vertex
 	 * and widget number from the widget vertex
@@ -1201,7 +1205,7 @@
 	devfs_handle_t		hub_vhdl    = xwidget_info_master_get(widget_info);
 	hubinfo_t		hub_info = 0;
 	nasid_t			nasid;
-	int			s;
+	unsigned long		s;
 
 	/* Use the nasid from the hub info hanging off the hub vertex
 	 * and widget number from the widget vertex
@@ -1253,25 +1257,23 @@
 	ii_iowa 	= REMOTE_HUB_L(nasid, IIO_IOWA);
 
 #if defined(SUPPORT_PRINTING_V_FORMAT)
-	cmn_err(CE_CONT, "Inquiry Info for %v\n", xconn);
+	printk("Inquiry Info for %v\n", xconn);
 #else
-	cmn_err(CE_CONT, "Inquiry Info for 0x%p\n", &xconn);
+	printk("Inquiry Info for 0x%x\n", xconn);
 #endif
 
-	cmn_err(CE_CONT,"\tDevices shutdown [ ");
+	printk("\tDevices shutdown [ ");
 
 	for (d = 0 ; d <= 7 ; d++)
 		if (!(ii_iidem & (IIO_IIDEM_WIDGETDEV_MASK(widget,d))))
-			cmn_err(CE_CONT, " %d", d);
+			printk(" %d", d);
 
-	cmn_err(CE_CONT,"]\n");
+	printk("]\n");
 
-	cmn_err(CE_CONT,
-		"\tInbound access ? %s\n",
+	printk("\tInbound access ? %s\n",
 		ii_iiwa & IIO_IIWA_WIDGET(widget) ? "yes" : "no");
 
-	cmn_err(CE_CONT,
-		"\tOutbound access ? %s\n",
+	printk("\tOutbound access ? %s\n",
 		ii_iowa & IIO_IOWA_WIDGET(widget) ? "yes" : "no");
 
 }
@@ -1300,6 +1302,7 @@
 	(xtalk_dmalist_drain_f *)	hub_dmalist_drain,
 
 	(xtalk_intr_alloc_f *)		hub_intr_alloc,
+	(xtalk_intr_alloc_f *)		hub_intr_alloc_nothd,
 	(xtalk_intr_free_f *)		hub_intr_free,
 	(xtalk_intr_connect_f *)	hub_intr_connect,
 	(xtalk_intr_disconnect_f *)	hub_intr_disconnect,
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/ip37.c linux/arch/ia64/sn/io/ip37.c
--- v2.4.3/linux/arch/ia64/sn/io/ip37.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/ip37.c	Thu Apr  5 12:51:47 2001
@@ -30,10 +30,6 @@
 		
 	ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid,IIO_WCR);
 
-	printk("hub_widget_id: Found Hub Widget ID 0x%x from Register 0x%p\n", ii_wcr.wcr_fields_s.wcr_widget_id, REMOTE_HUB_ADDR(nasid, IIO_WCR));
-
-	printk("hub_widget_id: Found Hub Widget 0x%lx wcr_reg_value 0x%lx\n", REMOTE_HUB_L(nasid,IIO_WCR), ii_wcr.wcr_reg_value);
-
 	return ii_wcr.wcr_fields_s.wcr_widget_id;
 }
 
@@ -64,8 +60,6 @@
 get_hub_chiprev(nasid_t nasid)
 {
 
-	printk("get_hub_chiprev: Hub Chip Rev 0x%lx\n",
-		(REMOTE_HUB_L(nasid, LB_REV_ID) & LRI_REV_MASK) >> LRI_REV_SHFT);
 	return ((REMOTE_HUB_L(nasid, LB_REV_ID) & LRI_REV_MASK)
 		                                         >> LRI_REV_SHFT);
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/klconflib.c linux/arch/ia64/sn/io/klconflib.c
--- v2.4.3/linux/arch/ia64/sn/io/klconflib.c	Fri Feb 16 16:02:34 2001
+++ linux/arch/ia64/sn/io/klconflib.c	Thu Apr  5 12:51:47 2001
@@ -82,7 +82,7 @@
 		}
 		index = j;
 		if (index == KLCF_NUM_COMPS(brd)) {
-			printf("find_component: Bad pointer: 0x%p\n", kli);
+			DBG("find_component: Bad pointer: 0x%p\n", kli);
 			return (klinfo_t *)NULL;
 		}
 		index++;	/* next component */
@@ -152,11 +152,6 @@
 	return (lboard_t *)NULL;
 }
 
-#ifndef CONFIG_IA64_SGI_IO
-#define tolower(c)	(isupper(c) ? (c) - 'A' + 'a' : (c))
-#define toupper(c)	(islower(c) ? (c) - 'a' + 'A' : (c))
-#endif
-
 
 /*
  * Convert a NIC name to a name for use in the hardware graph.
@@ -205,10 +200,6 @@
             !strncmp(new_name, "mio", 3) || 
 	    !strncmp(new_name, "media_io", 8))
 		strcpy(new_name, "baseio");
-#if !defined(CONFIG_SGI_IP35) && !defined(CONFIG_IA64_SGI_SN1) && !defined(CONFIG_IA64_GENERIC)
-	else if (!strncmp(new_name, "ip29", 4))
-		strcpy(new_name,SN00_MOTHERBOARD);
-#endif
 	else if (!strncmp(new_name, "divo", 4))
 		strcpy(new_name, "divo") ;
 
@@ -284,11 +275,11 @@
 
 	/*
  	 * PV # 540860
-	 * If the name is not 'baseio' or SN00 MOTHERBOARD
+	 * If the name is not 'baseio' 
 	 * get the lowest of all the names in the nic string.
 	 * This is needed for boards like divo, which can have
 	 * a bunch of daughter cards, but would like to be called
-	 * divo. We could do this for baseio and SN00 MOTHERBOARD
+	 * divo. We could do this for baseio 
  	 * but it has some special case names that we would not
  	 * like to disturb at this point.
 	 */
@@ -355,11 +346,7 @@
 	/*
 	 * look for boards that might contain an xbow or xbridge
 	 */
-#if SN0
-	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8);
-#else
-	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_PBRICK_XBOW);
-#endif
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW);
 	if (brd == NULL) return 0;
 		
 	if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
@@ -369,7 +356,7 @@
 	if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link))
 	    return 0;
 
-	printf("xbow_port_io_enabled:  brd 0x%p xbow_p 0x%p \n", brd, xbow_p);
+	DBG("xbow_port_io_enabled:  brd 0x%p xbow_p 0x%p \n", brd, xbow_p);
 
 	return 1;
 }
@@ -395,6 +382,9 @@
 			if (brd->brd_type == KLTYPE_META_ROUTER) {
 				board_name = EDGE_LBL_META_ROUTER;
 				hasmetarouter++;
+			} else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) {
+				board_name = EDGE_LBL_REPEATER_ROUTER;
+				hasmetarouter++;
 			} else
 				board_name = EDGE_LBL_ROUTER;
 			break;
@@ -420,22 +410,17 @@
 			
 	modnum = brd->brd_module;
 
-#if defined(SN0)
-	slot = brd->brd_slot;
-	get_slotname(slot, slot_name);
-
-	ASSERT(modnum >= 0);
-
-	sprintf(path, "%H/" EDGE_LBL_SLOT "/%s/%s", 
-		modnum, slot_name, board_name);
-#else
 	ASSERT(modnum != MODULE_UNKNOWN && modnum != INVALID_MODULE);
-#ifdef BRINGUP /* fix IP35 hwgraph */
-	sprintf(path, EDGE_LBL_MODULE "/%x/%s", modnum, board_name);
+#ifdef __ia64
+	{
+		char	buffer[16];
+		memset(buffer, 0, 16);
+		format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF);
+		sprintf(path, EDGE_LBL_MODULE "/%s/%s", buffer, board_name);
+	}
 #else
 	sprintf(path, "%H/%s", modnum, board_name);
 #endif
-#endif
 }
 
 /*
@@ -455,172 +440,8 @@
 }
 
 
-#ifndef CONFIG_IA64_SGI_IO
-#if 1
-/*
- *  find_gfxpipe(#)
- *
- *  XXXmacko
- *  This is only used by graphics drivers, and should be moved
- *  over to gfx/kern/graphics/SN0 as soon as it's convenient.
- */
-static klgfx_t *graphics_pipe_list = NULL;
-static devfs_handle_t hwgraph_all_gfxids = GRAPH_VERTEX_NONE;
-
-void
-setup_gfxpipe_link(devfs_handle_t vhdl,int pipenum)
-{
-	char idbuf[8];
-	extern graph_hdl_t hwgraph;
-
-	graph_info_add_LBL(hwgraph, vhdl, INFO_LBL_GFXID, INFO_DESC_EXPORT, 
-		(arbitrary_info_t)pipenum);
-	if (hwgraph_all_gfxids == GRAPH_VERTEX_NONE)
-		hwgraph_path_add(hwgraph_root, EDGE_LBL_GFX, &hwgraph_all_gfxids);
-	sprintf(idbuf, "%d", pipenum);
-	hwgraph_edge_add(hwgraph_all_gfxids, vhdl, idbuf);
-
-}
-#endif
-
-/* 
- * find the pipenum'th logical graphics pipe (KLCLASS_GFX)
- */
-lboard_t *
-find_gfxpipe(int pipenum)
-{
-        gda_t           *gdap;
-        cnodeid_t       cnode;
-        nasid_t         nasid;
-        lboard_t        *lb;
-	klgfx_t		*kg,**pkg;
-	int		i;
-
-        gdap = (gda_t *)GDA_ADDR(get_nasid());
-        if (gdap->g_magic != GDA_MAGIC)
-        	return NULL;
-
-	if (!graphics_pipe_list) {
-		/* for all nodes */
-        	for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) {
-                	nasid = gdap->g_nasidtable[cnode];
-                	if (nasid == INVALID_NASID)
-                        	continue;
-			lb = KL_CONFIG_INFO(nasid) ;
-			while (lb = find_lboard_class(lb, KLCLASS_GFX)) {
-				moduleid_t kgm, pkgm;
-				int	kgs, pkgs;
-
-#if defined(DEBUG) && (defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)) && defined(BRINGUP)
-				printf("find_gfxpipe(): PIPE: %s mod %M slot %d\n",lb?lb->brd_name:"!LBRD",
-					lb->brd_module,lb->brd_slot);
-#endif
-				/* insert lb into list */
-				if (!(kg = (klgfx_t*)find_first_component(lb,KLSTRUCT_GFX))) {
-					lb = KLCF_NEXT(lb);
-					continue;
-				}
-				/* set moduleslot now that we have brd_module set */
-				kg->moduleslot = (lb->brd_module << 8) | SLOTNUM_GETSLOT(lb->brd_slot);
-				/* make sure board has device flag set */
-				kg->gfx_info.flags |= KLINFO_DEVICE;
-				if (kg->cookie < KLGFX_COOKIE) {
-				    kg->gfx_next_pipe = NULL;
-				    kg->cookie = KLGFX_COOKIE;
-				}
-
-				kgm = kg->moduleslot>>8;
-				kgs = kg->moduleslot&0xff;
-				pkg = &graphics_pipe_list;
-				while (*pkg) {
-					pkgm = (*pkg)->moduleslot>>8;
-					pkgs = (*pkg)->moduleslot&0xff;
-
-					if (!(MODULE_CMP(kgm, pkgm) > 0 ||
-					      (MODULE_CMP(kgm, pkgm) == 0 &&
-					       kgs > pkgs)))
-					    break;
-
-					pkg = &(*pkg)->gfx_next_pipe;
-				}
-				kg->gfx_next_pipe = *pkg;
-				*pkg = kg;
-				lb = KLCF_NEXT(lb);
-			}
-		}
-#ifdef FIND_GFXPIPE_DEBUG
-		i = 0;
-		kg = graphics_pipe_list;
-		while (kg) {
-			lboard_t *lb;
-#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
-			lb = find_lboard_class(KL_CONFIG_INFO(kg->gfx_info.nasid), KLCLASS_GFX);
-#else
-#error Need to figure out how to find graphics boards ...
-#endif
-#if defined(SUPPORT_PRINTING_M_FORMAT)
-			printf("find_gfxpipe(): %s pipe %d mod %M slot %d\n",lb?lb->brd_name:"!LBRD",i,
-				(kg->moduleslot>>8),(kg->moduleslot&0xff));
-#else
-			printf("find_gfxpipe(): %s pipe %d mod 0x%x slot %d\n",lb?lb->brd_name:"!LBRD",i,
-				(kg->moduleslot>>8),(kg->moduleslot&0xff));
-#endif
-			kg = kg->gfx_next_pipe;
-			i++;
-		}
-#endif
-        }
-
-	i = 0;
-	kg = graphics_pipe_list;
-	while (kg && (i < pipenum)) {
-		kg = kg->gfx_next_pipe;
-		i++;
-		}
-
-	if (!kg) return NULL;
-
-#if defined(SN0)
-	return find_lboard_modslot(KL_CONFIG_INFO(kg->gfx_info.nasid),
-				(kg->moduleslot>>8),
-				SLOTNUM_XTALK_CLASS|(kg->moduleslot&0xff));
-#elif defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
-	return find_lboard_class(KL_CONFIG_INFO(kg->gfx_info.nasid), KLCLASS_GFX);
-#else
-#error Need to figure out how to find graphics boards ...
-#endif
-}
-#endif
-
-
 #define MHZ	1000000
 
-#ifndef CONFIG_IA64_SGI_IO
-uint
-cpu_cycles_adjust(uint orig_cycles)
-{
-	klcpu_t *acpu;
-	uint speed;
-
-	acpu  = nasid_slice_to_cpuinfo(get_nasid(), get_slice());
-
-	if (acpu == NULL) return orig_cycles;
-
-	/*
-	 * cpu cycles seem to be half of the real value, hack and mult by 2
-	 * for now.
-	 */
-	speed = (orig_cycles * 2) / MHZ;
-
-	/*
-	 * if the cpu thinks its running at some random speed nowhere close 
-	 * the programmed speed, do nothing.
-	 */
-	if ((speed < (acpu->cpu_speed - 2)) || (speed > (acpu->cpu_speed + 2)))
-	    return orig_cycles;
-	return (acpu->cpu_speed * MHZ/2);
-}
-#endif /* CONFIG_IA64_SGI_IO */
 
 /* Get the canonical hardware graph name for the given pci component
  * on the given io board.
@@ -633,9 +454,6 @@
 	moduleid_t 	modnum;
 	slotid_t 	slot;
 	char 		board_name[20];
-#ifdef SN0
-	char 		slot_name[SLOTNUM_MAXLENGTH];
-#endif
 
 	ASSERT(brd);
 
@@ -646,13 +464,7 @@
 	 * into a string 
 	 */
 	slot = brd->brd_slot;
-#ifdef SN0
-	get_slotname(slot, slot_name);
-
-	ASSERT(modnum >= 0);
-#else
 	ASSERT(modnum != MODULE_UNKNOWN && modnum != INVALID_MODULE);
-#endif
 
 	/* Get the io board name  */
 	if (!brd || (brd->brd_sversion < 2)) {
@@ -662,18 +474,10 @@
 	}
 
 	/* Give out the canonical  name of the pci device*/
-#ifdef SN0
-	sprintf(name, 
-		"/hw/"EDGE_LBL_MODULE "/%M/"EDGE_LBL_SLOT"/%s/%s/"
-		EDGE_LBL_PCI"/%d", 
-		modnum, slot_name, board_name,KLCF_BRIDGE_W_ID(component));
-#elif defined (CONFIG_SGI_IP35)  || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
 	sprintf(name, 
 		"/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLOT"/%s/"
 		EDGE_LBL_PCI"/%d", 
 		modnum, board_name,KLCF_BRIDGE_W_ID(component));
-#endif
-	
 }
 
 /*
@@ -894,90 +698,6 @@
 }
 
 #include "asm/sn/sn_private.h"
-#ifndef CONFIG_IA64_SGI_IO
-/*
- * Given a physical address get the name of memory dimm bank
- * in a hwgraph name format.
- */
-void
-membank_pathname_get(paddr_t paddr,char *name)
-{
-	cnodeid_t	cnode;
-	char		slotname[SLOTNUM_MAXLENGTH];
-
-	cnode = paddr_cnode(paddr);
-	/* Make sure that we have a valid name buffer */
-	if (!name)
-		return;
-
-	name[0] = 0;
-	/* Make sure that the cnode is valid */
-	if ((cnode == CNODEID_NONE) || (cnode > numnodes))
-		return;
-	/* Given a slotid(class:type) get the slotname */
-#if defined (SN0)
-	get_slotname(NODE_SLOTID(cnode),slotname);
-	sprintf(name,
-		"/hw/"EDGE_LBL_MODULE"/%M/"EDGE_LBL_SLOT"/%s/"EDGE_LBL_NODE
-		"/"EDGE_LBL_MEMORY"/dimm_bank/%d",
-		NODE_MODULEID(cnode),slotname,paddr_dimm(paddr));
-#elif defined (CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
-	sprintf(name,
-		"/dev/hw/"EDGE_LBL_MODULE"/%M/"EDGE_LBL_NODE
-		"/"EDGE_LBL_MEMORY"/dimm_bank/%d",
-		NODE_MODULEID(cnode),paddr_dimm(paddr));
-#endif
-}
-
-
-
-int
-membank_check_mixed_hidensity(nasid_t nasid)
-{
-	lboard_t *brd;
-	klmembnk_t *mem;
-	int min_size = 1024, max_size = 0;
-	int bank, mem_size;
-
-	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
-	ASSERT(brd);
-
-	mem = (klmembnk_t *)find_first_component(brd, KLSTRUCT_MEMBNK);
-	ASSERT(mem);
-
-
-	for (mem_size = 0, bank = 0; bank < MD_MEM_BANKS; bank++) {
-		mem_size = KLCONFIG_MEMBNK_SIZE(mem, bank);
-		if (mem_size < min_size)
-		    min_size = mem_size;
-		if (mem_size > max_size)
-		    max_size = mem_size;
-	}
-	
-	if ((max_size == 512) && (max_size != min_size))
-	    return 1;
-
-	return 0;
-}
-
-
-int
-mem_mixed_hidensity_banks(void)
-{
-	cnodeid_t cnode;
-	nasid_t nasid;
-
-	for (cnode = 0; cnode < maxnodes; cnode++) {
-		nasid = COMPACT_TO_NASID_NODEID(cnode);
-		if (nasid == INVALID_NASID)
-		    continue;
-		if (membank_check_mixed_hidensity(nasid))
-		    return 1;
-	}
-	return 0;
-
-}
-#endif /* CONFIG_IA64_SGI_IO */
 
 xwidgetnum_t
 nodevertex_widgetnum_get(devfs_handle_t node_vtx)
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/klgraph.c linux/arch/ia64/sn/io/klgraph.c
--- v2.4.3/linux/arch/ia64/sn/io/klgraph.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/klgraph.c	Thu Apr  5 12:51:47 2001
@@ -23,18 +23,15 @@
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
 
-#include <asm/sn/cmn_err.h>
 #include <asm/sn/agent.h>
-#ifdef CONFIG_IA64_SGI_IO
 #include <asm/sn/kldir.h>
-#endif
 #include <asm/sn/gda.h> 
 #include <asm/sn/klconfig.h>
 #include <asm/sn/router.h>
 #include <asm/sn/xtalk/xbow.h>
 #include <asm/sn/hcl_util.h>
 
-#define KLGRAPH_DEBUG 1
+/* #define KLGRAPH_DEBUG 1 */
 #ifdef KLGRAPH_DEBUG
 #define GRPRINTF(x)	printk x
 #define CE_GRPANIC	CE_PANIC
@@ -48,25 +45,6 @@
 extern char arg_maxnodes[];
 extern int maxnodes;
 
-#ifndef BRINGUP
-/*
- * Gets reason for diagval using table lookup.
- */
-static char*
-get_diag_string(uint diagcode)
-{
-  int num_entries;
-  int i;
-  num_entries = sizeof(diagval_map) / sizeof(diagval_t);
-  for (i = 0; i < num_entries; i++){
-    if ((unchar)diagval_map[i].dv_code == (unchar)diagcode)
-      return diagval_map[i].dv_msg;
-  }
-  return "Unknown";
-}
-
-#endif /* ndef BRINGUP */
-
 
 /*
  * Support for verbose inventory via hardware graph. 
@@ -105,7 +83,7 @@
 		klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t));
 	baseio_inventory->im_type = INV_IO6PROM;
 	/* Read the io6prom revision from the nvram */
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef LATER
 	nvram_prom_version_get(&version,&revision);
 #endif
 	/* Store the revision info  in the inventory */
@@ -169,7 +147,7 @@
 	(void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv);
 	rc = device_master_set(myhubv, node_vertex);
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	/*
 	 * Activate when we support hub stats.
 	 */
@@ -178,8 +156,7 @@
 #endif
 
 	if (rc != GRAPH_SUCCESS) {
-		cmn_err(CE_WARN,
-			"klhwg_add_hub: Can't add hub info label 0x%p, code %d",
+		PRINT_WARNING("klhwg_add_hub: Can't add hub info label 0x%p, code %d",
 			myhubv, rc);
 	}
 
@@ -187,15 +164,12 @@
 
 #ifndef BRINGUP
 	init_hub_stats(cnode, NODEPDA(cnode));
-#endif /* ndef BRINGUP */
-
-#ifndef CONFIG_IA64_SGI_IO
 	sndrv_attach(myhubv);
 #else
 	/*
 	 * Need to call our driver to do the attach?
 	 */
-	printk("klhwg_add_hub: Need to add code to do the attach.\n");
+	FIXME("klhwg_add_hub: Need to add code to do the attach.\n");
 #endif
 }
 
@@ -350,7 +324,7 @@
 		rps_invent->ir_gen.ig_flag = INVENT_ENABLED;
 }
 
-#endif /* ndef BRINGUP */
+#endif /* BRINGUP */
 
 void
 klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid)
@@ -366,7 +340,7 @@
 
 #if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || defined(CONFIG_IA64_GENERIC)
 	if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid),
-				KLTYPE_PBRICK_XBOW)) == NULL)
+				KLTYPE_IOBRICK_XBOW)) == NULL)
 			return;
 #endif
 
@@ -380,7 +354,7 @@
 	    == NULL)
 	    return;
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	/*
 	 * We cannot support this function in devfs .. see below where 
 	 * we use hwgraph_path_add() to create this vertex with a known 
@@ -390,21 +364,19 @@
 	ASSERT(err == GRAPH_SUCCESS);
 
 	xswitch_vertex_init(xbow_v);
-#endif /* !CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 
 	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
 		if (!XBOW_PORT_TYPE_HUB(xbow_p, widgetnum)) 
 		    continue;
 
 		hub_nasid = XBOW_PORT_NASID(xbow_p, widgetnum);
-		printk("klhwg_add_xbow: Found xbow port type hub hub_nasid %d widgetnum %d\n", hub_nasid, widgetnum);
 		if (hub_nasid == INVALID_NASID) {
-			cmn_err(CE_WARN, "hub widget %d, skipping xbow graph\n", widgetnum);
+			PRINT_WARNING("hub widget %d, skipping xbow graph\n", widgetnum);
 			continue;
 		}
 
 		hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid);
-		printk("klhwg_add_xbow: cnode %d cnode %d\n", nasid_to_compact_node[0], nasid_to_compact_node[1]);
 
 		if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) {
 			continue;
@@ -412,21 +384,18 @@
 			
 		hubv = cnodeid_to_vertex(hub_cnode);
 
-#ifdef CONFIG_IA64_SGI_IO
-		printk("klhwg_add_xbow: Hub Vertex found = %p hub_cnode %d\n", hubv, hub_cnode);
 		err = hwgraph_path_add(hubv, EDGE_LBL_XTALK, &xbow_v);
                 if (err != GRAPH_SUCCESS) {
                         if (err == GRAPH_DUP)
-                                cmn_err(CE_WARN, "klhwg_add_xbow: Check for "
+                                PRINT_WARNING("klhwg_add_xbow: Check for "
                                         "working routers and router links!");
 
-                        cmn_err(CE_GRPANIC, "klhwg_add_xbow: Failed to add "
+                        PRINT_PANIC("klhwg_add_xbow: Failed to add "
                                 "edge: vertex 0x%p (0x%p) to vertex 0x%p (0x%p),"
                                 "error %d\n",
                                 hubv, hubv, xbow_v, xbow_v, err);
                 }
 		xswitch_vertex_init(xbow_v); 
-#endif
 
 		NODEPDA(hub_cnode)->xbow_vhdl = xbow_v;
 
@@ -443,14 +412,14 @@
 		GRPRINTF(("klhwg_add_xbow: adding port nasid %d %s to vertex 0x%p\n",
 			hub_nasid, EDGE_LBL_XTALK, hubv));
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 		err = hwgraph_edge_add(hubv, xbow_v, EDGE_LBL_XTALK);
 		if (err != GRAPH_SUCCESS) {
 			if (err == GRAPH_DUP)
-				cmn_err(CE_WARN, "klhwg_add_xbow: Check for "
+				PRINT_WARNING("klhwg_add_xbow: Check for "
 					"working routers and router links!");
 
-			cmn_err(CE_GRPANIC, "klhwg_add_xbow: Failed to add "
+			PRINT_PANIC("klhwg_add_xbow: Failed to add "
 				"edge: vertex 0x%p (0x%p) to vertex 0x%p (0x%p), "
 				"error %d\n",
 				hubv, hubv, xbow_v, xbow_v, err);
@@ -488,9 +457,8 @@
 			path_buffer, hwgraph_root));
 		rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
 
-		printk("klhwg_add_node: rv = %d graph success %d node_vertex 0x%p\n", rv, GRAPH_SUCCESS, node_vertex);
 		if (rv != GRAPH_SUCCESS)
-			cmn_err(CE_PANIC, "Node vertex creation failed.  "
+			PRINT_PANIC("Node vertex creation failed.  "
 					  "Path == %s",
 				path_buffer);
 
@@ -504,11 +472,8 @@
 		if(!board_disabled) {
 			mark_nodevertex_as_node(node_vertex,
 					    cnode + board_disabled * numnodes);
-			printk("klhwg_add_node: node_vertex %p, cnode %d numnodes %d\n", node_vertex, cnode, numnodes);
 
 			s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer));
-			printk("klhwg_add_node: s %s\n", s);
-
 			NODEPDA(cnode)->hwg_node_name =
 						kmalloc(strlen(s) + 1,
 						GFP_KERNEL);
@@ -581,7 +546,7 @@
 			rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
 
 			if (rv != GRAPH_SUCCESS)
-				cmn_err(CE_PANIC, "Router vertex creation "
+				PRINT_PANIC("Router vertex creation "
 						  "failed.  Path == %s",
 					path_buffer);
 
@@ -629,12 +594,11 @@
 			return;
 
 	if (rc != GRAPH_SUCCESS)
-		cmn_err(CE_WARN, "Can't find router: %s", path_buffer);
+		PRINT_WARNING("Can't find router: %s", path_buffer);
 
 	/* We don't know what to do with multiple router components */
 	if (brd->brd_numcompts != 1) {
-		cmn_err(CE_PANIC,
-			"klhwg_connect_one_router: %d cmpts on router\n",
+		PRINT_PANIC("klhwg_connect_one_router: %d cmpts on router\n",
 			brd->brd_numcompts);
 		return;
 	}
@@ -668,7 +632,7 @@
 		if (rc != GRAPH_SUCCESS) {
 			if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
 				continue;
-			cmn_err(CE_PANIC, "Can't find router: %s", dest_path);
+			PRINT_PANIC("Can't find router: %s", dest_path);
 		}
 		GRPRINTF(("klhwg_connect_one_router: Link from %s/%d to %s\n",
 			  path_buffer, port, dest_path));
@@ -685,7 +649,7 @@
 		}
 
 		if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes))
-			cmn_err(CE_GRPANIC, "Can't create edge: %s/%s to vertex 0x%p error 0x%x\n",
+			PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n",
 				path_buffer, dest_path, dest_hndl, rc);
 		
 	}
@@ -768,7 +732,7 @@
 		rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl);
 
 		if (rc != GRAPH_SUCCESS)
-			cmn_err(CE_WARN, "Can't find hub: %s", path_buffer);
+			PRINT_WARNING("Can't find hub: %s", path_buffer);
 
 		dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
 				hub->hub_port.port_nasid,
@@ -782,7 +746,7 @@
 		if (rc != GRAPH_SUCCESS) {
 			if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
 				continue;
-			cmn_err(CE_PANIC, "Can't find board: %s", dest_path);
+			PRINT_PANIC("Can't find board: %s", dest_path);
 		} else {
 		
 
@@ -792,7 +756,7 @@
 			rc = hwgraph_edge_add(hub_hndl, dest_hndl, EDGE_LBL_INTERCONNECT);
 
 			if (rc != GRAPH_SUCCESS)
-				cmn_err(CE_GRPANIC, "Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n",
+				PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n",
 				path_buffer, dest_path, dest_hndl, rc);
 
 		}
@@ -815,7 +779,7 @@
 					 */
 	char		device_name[MAXDEVNAME];
 	
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	device_admin_table_init();
 #endif
 	for(cnode = 0; cnode < numnodes; cnode++) {
@@ -853,7 +817,7 @@
 				device_component_canonical_name_get(board,
 							    component,
 							    device_name);
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 				device_admin_table_update(device_name,
 							  ADMIN_LBL_DISABLED,
 							  "yes");
@@ -877,13 +841,20 @@
 	char		name[128];
 	devfs_handle_t	vhdl;
 	int		rc;
+	char		buffer[16];
 
 	/* Add devices under each module */
 
 	for (cm = 0; cm < nummodules; cm++) {
 		/* Use module as module vertex fastinfo */
 
+#ifdef __ia64
+		memset(buffer, 0, 16);
+		format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF);
+		sprintf(name, EDGE_LBL_MODULE "/%s", buffer);
+#else
 		sprintf(name, EDGE_LBL_MODULE "/%x", modules[cm]->id);
+#endif
 
 		rc = hwgraph_path_add(hwgraph_root, name, &vhdl);
 		ASSERT(rc == GRAPH_SUCCESS);
@@ -893,9 +864,15 @@
 
 		/* Add system controller */
 
+#ifdef __ia64
+		sprintf(name,
+			EDGE_LBL_MODULE "/%s/" EDGE_LBL_L1,
+			buffer);
+#else
 		sprintf(name,
 			EDGE_LBL_MODULE "/%x/" EDGE_LBL_L1,
 			modules[cm]->id);
+#endif
 
 		rc = hwgraph_path_add(hwgraph_root, name, &vhdl);
 		ASSERT_ALWAYS(rc == GRAPH_SUCCESS); 
@@ -905,7 +882,7 @@
 				     INFO_LBL_ELSC,
 				     (arbitrary_info_t) (__psint_t) 1);
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 		sndrv_attach(vhdl);
 #else
 		/*
@@ -923,13 +900,10 @@
 	gda_t		*gdap;
 	cnodeid_t	cnode;
 
-#ifdef SIMULATED_KLGRAPH
-	//gdap = 0xa800000000011000;
-	gdap = (gda_t *)0xe000000000011000;
-	printk("klhwg_add_all_nodes: SIMULATED_KLGRAPH FIXME: gdap= 0x%p\n", gdap);
-#else
-	gdap = GDA;
-#endif /* SIMULATED_KLGRAPH */
+	gdap = (gda_t *)0xe000000000002400;
+
+	FIXME("klhwg_add_all_nodes: FIX GDA\n");
+
 	for (cnode = 0; cnode < numnodes; cnode++) {
 		ASSERT(gdap->g_nasidtable[cnode] != INVALID_NASID);
 		klhwg_add_node(hwgraph_root, cnode, gdap);
@@ -938,12 +912,7 @@
 	for (cnode = 0; cnode < numnodes; cnode++) {
 		ASSERT(gdap->g_nasidtable[cnode] != INVALID_NASID);
 
-#ifndef CONFIG_IA64_SGI_IO
 		klhwg_add_xbow(cnode, gdap->g_nasidtable[cnode]);
-#else
-		printk("klhwg_add_all_nodes: Fix me by getting real nasid\n");
-		klhwg_add_xbow(cnode, 0);
-#endif
 	}
 
 	/*
@@ -959,7 +928,7 @@
 	 * routers in the system.
 	 */
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	router_guardians_set(hwgraph_root);
 #endif
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/klgraph_hack.c linux/arch/ia64/sn/io/klgraph_hack.c
--- v2.4.3/linux/arch/ia64/sn/io/klgraph_hack.c	Fri Feb 16 16:02:34 2001
+++ linux/arch/ia64/sn/io/klgraph_hack.c	Thu Apr 12 12:16:35 2001
@@ -15,7 +15,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <asm/sn/sgi.h>
@@ -35,55 +34,6 @@
 extern void clear_ii_error(void);
 #endif /* BRINGUP */
 
-void
-simulated_BW0_init(void)
-{
-
-	unsigned long *cnode0_hub;
-	unsigned long hub_widget = 0x1000000;
-	unsigned long hub_offset = 0x800000;
-	unsigned long hub_reg_base = 0;
-	extern void * vmalloc(unsigned long);
-
-	memset(&nasid_to_compact_node[0], 0, sizeof(cnodeid_t) * MAX_NASIDS);
-
-	BW0 = vmalloc(0x10000000);
-	if (BW0 == NULL) {
-		printk("Darn it .. cannot create space for Big Window 0\n");
-	}
-	printk("BW0: Start Address %p\n", BW0);
-	
-	memset(BW0+(0x10000000 - 8), 0xf, 0x8);
-
-	printk("BW0: Last WORD address %p has value 0x%lx\n", (char *)(BW0 +(0x10000000 - 8)), *(long *)(BW0 +(0x10000000 - 8)));
-
-	printk("XWIDGET 8 Address = 0x%p\n", (unsigned long *)(NODE_SWIN_BASE(0, 8)) ); 
-
-	/*
-	 * Do some HUB Register Hack ..
-	 */
-	hub_reg_base = (unsigned long)BW0 + hub_widget + hub_offset;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_WID); *cnode0_hub = 0x1c110049;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_WSTAT); *cnode0_hub = 0x0;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_WCR); *cnode0_hub = 0x401b;
-	printk("IIO_WCR address = 0x%p\n", cnode0_hub);
-
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ILAPR); *cnode0_hub = 0xffffffffffffffff;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ILAPO); *cnode0_hub = 0x0;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IOWA); *cnode0_hub = 0xff01;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IIWA); *cnode0_hub = 0xff01;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IIDEM); *cnode0_hub = 0xffffffffffffffff;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ILCSR); *cnode0_hub = 0x3fc03ff640a;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ILLR); *cnode0_hub = 0x0;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IIDSR); *cnode0_hub = 0x1000040;
-#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IGFX0); *cnode0_hub = 0x0;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_IGFX1); *cnode0_hub = 0x0;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ISCR0); *cnode0_hub = 0x23d;
-        cnode0_hub = (unsigned long *)(hub_reg_base + IIO_ISCR1); *cnode0_hub = 0x0;
-#endif	/* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */
-}
-
 #define SYNERGY_WIDGET          ((char *)0xc0000e0000000000)
 #define SYNERGY_SWIZZLE         ((char *)0xc0000e0000000400)
 #define HUBREG                  ((char *)0xc0000a0001e00000)
@@ -136,10 +86,10 @@
 	klxbow_t	*klxbow_ptr;
 	klinfo_t	*klinfo_ptr;
 	klcomp_t	*klcomp_ptr;
+#if 0
 	uint64_t	*tmp;
 	volatile u32	*tmp32;
 
-#if 0
 	/* Preset some values */
 	/* Write IOERR clear to clear the CRAZY bit in the status */
 	tmp = (uint64_t *)0xc0000a0001c001f8; *tmp = (uint64_t)0xffffffff;
@@ -164,7 +114,6 @@
 	*tmp32 = 0xba98;
 	tmp32 = (volatile u32 *)0xc0000a000f000288L;
 	*tmp32 = 0xba98;
-#endif
 
 printk("Widget ID Address 0x%p Value 0x%lx\n", (uint64_t *)0xc0000a0001e00000, *( (volatile uint64_t *)0xc0000a0001e00000) );
 
@@ -181,6 +130,7 @@
 
 printk("Xbow ID Address 0x%p Value 0x%x\n", (uint64_t *)0xc000020000000004, *( (volatile uint32_t *)0xc000020000000004) );
 
+#endif
 
 	if ( test )
 		test_io_regs();
@@ -210,9 +160,8 @@
 	 */
 	linux_klcfg = (kl_config_hdr_t *)0xe000000000030000;
 	if (linux_klcfg->ch_magic == 0xbeedbabe) {
-		printk("Linux Kernel Booted from Disk\n");
+		return;
 	} else {
-		printk("Linux Kernel Booted from PROM\n");
 		linux_klcfg = kl_hdr_ptr;
 	}
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/l1.c linux/arch/ia64/sn/io/l1.c
--- v2.4.3/linux/arch/ia64/sn/io/l1.c	Tue Mar  6 19:44:35 2001
+++ linux/arch/ia64/sn/io/l1.c	Thu Apr  5 12:51:47 2001
@@ -34,6 +34,7 @@
 #include <linux/types.h>
 #include <linux/config.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/iograph.h>
 #include <asm/sn/invent.h>
@@ -42,7 +43,6 @@
 #include <asm/sn/labelcl.h>
 #include <asm/sn/eeprom.h>
 #include <asm/sn/ksys/i2c.h>
-#include <asm/sn/cmn_err.h>
 #include <asm/sn/router.h>
 #include <asm/sn/module.h>
 #include <asm/sn/ksys/l1.h>
@@ -51,6 +51,20 @@
 
 #include <asm/sn/sn1/uart16550.h>
 
+/*
+ * Delete this when atomic_clear is part of atomic.h.
+ */
+static __inline__ int
+atomic_clear (int i, atomic_t *v)
+{
+	__s32 old, new;
+
+	do {
+		old = atomic_read(v);
+		new = old & ~i;
+	} while (ia64_cmpxchg("acq", v, old, new, sizeof(atomic_t)) != old);
+	return new;
+}
 
 #if defined(EEPROM_DEBUG)
 #define db_printf(x) printk x
@@ -73,6 +87,7 @@
 /* location of uart receive/xmit data register */
 #define L1_UART_BASE(n)	((ulong)REMOTE_HSPEC_ADDR((n), HSPEC_UART_0))
 #define LOCAL_HUB	LOCAL_HUB_ADDR
+#define LOCK_HUB	REMOTE_HUB_ADDR
 
 #define ADDR_L1_REG(n, r)	\
     (L1_UART_BASE(n) | ( (r) << 3 ))
@@ -84,21 +99,10 @@
     ( SD(ADDR_L1_REG((n), (r)), (v)) )
 
 
-/* Avoid conflicts with symmon...*/
-#define CONS_HW_LOCK(x)
-#define CONS_HW_UNLOCK(x)
-
-#define L1_CONS_HW_LOCK(sc)	CONS_HW_LOCK(sc->uart == BRL1_LOCALUART)
-#define L1_CONS_HW_UNLOCK(sc)	CONS_HW_UNLOCK(sc->uart == BRL1_LOCALUART)
-
-#if DEBUG
-static int debuglock_ospl; /* For CONS_HW_LOCK macro */
-#endif
-
 /* UART-related #defines */
 
 #define UART_BAUD_RATE		57600
-#define UART_FIFO_DEPTH		16
+#define UART_FIFO_DEPTH		0xf0
 #define UART_DELAY_SPAN		10
 #define UART_PUTC_TIMEOUT	50000
 #define UART_INIT_TIMEOUT	100000
@@ -146,6 +150,9 @@
 	    _xyz[0] = _b[_i++];			\
 	}
 #else	/* BIG_ENDIAN */
+
+extern char *bcopy(const char * src, char * dest, int count);
+
 #define COPY_INT_TO_BUFFER(_b, _i, _n)			\
 	{						\
 		bcopy((char *)&_n, _b, sizeof(_n));	\
@@ -165,13 +172,148 @@
 	}
 #endif	/* LITTLE_ENDIAN */
 
-int atomicAddInt(int *int_ptr, int value);
-int atomicClearInt(int *int_ptr, int value);
 void kmem_free(void *where, int size);
 
 #define BCOPY(x,y,z)	memcpy(y,x,z)
 
-extern char *bcopy(const char * src, char * dest, int count);
+/*
+ * Console locking defines and functions.
+ *
+ */
+
+#ifdef BRINGUP
+#define FORCE_CONSOLE_NASID
+#endif
+
+#define HUB_LOCK		16
+
+#define PRIMARY_LOCK_TIMEOUT    10000000
+#define HUB_LOCK_REG(n)         LOCK_HUB(n, MD_PERF_CNT0)
+
+#define SET_BITS(reg, bits)     SD(reg, LD(reg) |  (bits))
+#define CLR_BITS(reg, bits)     SD(reg, LD(reg) & ~(bits))
+#define TST_BITS(reg, bits)     ((LD(reg) & (bits)) != 0)
+
+#define HUB_TEST_AND_SET(n)	LD(LOCK_HUB(n,LB_SCRATCH_REG3_RZ))
+#define HUB_CLEAR(n)		SD(LOCK_HUB(n,LB_SCRATCH_REG3),0)
+
+#define RTC_TIME_MAX		((rtc_time_t) ~0ULL)
+
+
+/*
+ * primary_lock
+ *
+ *   Allows CPU's 0-3  to mutually exclude the hub from one another by
+ *   obtaining a blocking lock.  Does nothing if only one CPU is active.
+ *
+ *   This lock should be held just long enough to set or clear a global
+ *   lock bit.  After a relatively short timeout period, this routine
+ *   figures something is wrong, and steals the lock. It does not set
+ *   any other CPU to "dead".
+ */
+inline void
+primary_lock(nasid_t nasid)
+{
+	rtc_time_t          expire;
+
+	expire = rtc_time() + PRIMARY_LOCK_TIMEOUT;
+
+	while (HUB_TEST_AND_SET(nasid)) {
+		if (rtc_time() > expire) {
+			HUB_CLEAR(nasid);
+		}
+	}
+}
+
+/*
+ * primary_unlock (internal)
+ *
+ *   Counterpart to primary_lock
+ */
+
+inline void
+primary_unlock(nasid_t nasid)
+{
+	HUB_CLEAR(nasid);
+}
+
+/*
+ * hub_unlock
+ *
+ *   Counterpart to hub_lock_timeout and hub_lock
+ */
+
+inline void
+hub_unlock(nasid_t nasid, int level)
+{
+	uint64_t mask = 1ULL << level;
+
+	primary_lock(nasid);
+	CLR_BITS(HUB_LOCK_REG(nasid), mask);
+	primary_unlock(nasid);
+}
+
+/*
+ * hub_lock_timeout
+ *
+ *   Uses primary_lock to implement multiple lock levels.
+ *
+ *   There are 20 lock levels from 0 to 19 (limited by the number of bits
+ *   in HUB_LOCK_REG).  To prevent deadlock, multiple locks should be
+ *   obtained in order of increasingly higher level, and released in the
+ *   reverse order.
+ *
+ *   A timeout value of 0 may be used for no timeout.
+ *
+ *   Returns 0 if successful, -1 if lock times out.
+ */
+
+inline int
+hub_lock_timeout(nasid_t nasid, int level, rtc_time_t timeout)
+{
+	uint64_t mask = 1ULL << level;
+	rtc_time_t expire = (timeout ?  rtc_time() + timeout : RTC_TIME_MAX);
+	int done    = 0;
+
+	while (! done) {
+		while (TST_BITS(HUB_LOCK_REG(nasid), mask)) {
+			if (rtc_time() > expire)
+				return -1;
+		}
+
+		primary_lock(nasid);
+
+		if (! TST_BITS(HUB_LOCK_REG(nasid), mask)) {
+			SET_BITS(HUB_LOCK_REG(nasid), mask);
+			done = 1;
+		}
+		primary_unlock(nasid);
+	}
+	return 0;
+}
+
+
+#define LOCK_TIMEOUT	(0x1500000 * 1) /* 0x1500000 is ~30 sec */
+
+inline void
+lock_console(nasid_t nasid)
+{
+	int ret;
+
+	ret = hub_lock_timeout(nasid, HUB_LOCK, (rtc_time_t)LOCK_TIMEOUT);
+	if ( ret != 0 ) {
+		/* timeout */
+		hub_unlock(nasid, HUB_LOCK);
+		/* If the 2nd lock fails, just pile ahead.... */
+		hub_lock_timeout(nasid, HUB_LOCK, (rtc_time_t)LOCK_TIMEOUT);
+	}
+}
+
+inline void
+unlock_console(nasid_t nasid)
+{
+	hub_unlock(nasid, HUB_LOCK);
+}
 
 
 int 
@@ -189,7 +331,7 @@
     UART_DELAY( delay_span );
 }
 
-#define UART_PUTC_READY(n)	(READ_L1_UART_REG((n), REG_LSR) & LSR_XHRE)
+#define UART_PUTC_READY(n)      ( (READ_L1_UART_REG((n), REG_LSR) & LSR_XHRE) && (READ_L1_UART_REG((n), REG_MSR) & MSR_CTS) )
 
 static int
 uart_putc( l1sc_t *sc ) 
@@ -198,6 +340,10 @@
     /* need a delay to avoid dropping chars */
     UART_DELAY(57);
 #endif
+#ifdef FORCE_CONSOLE_NASID
+    /* We need this for the console write path _elscuart_flush() -> brl1_send() */
+    sc->nasid = 0;
+#endif
     WRITE_L1_UART_REG( sc->nasid, REG_DAT,
 		       sc->send[sc->sent] );
     return UART_SUCCESS;
@@ -210,6 +356,10 @@
     u_char lsr_reg = 0;
     nasid_t nasid = sc->nasid;
 
+#ifdef FORCE_CONSOLE_NASID
+    nasid = sc->nasid = 0;
+#endif
+
     if( (lsr_reg = READ_L1_UART_REG( nasid, REG_LSR )) & 
 	(LSR_RCA | LSR_PARERR | LSR_FRMERR) ) 
     {
@@ -246,7 +396,8 @@
 	}
     }
 
-    L1_CONS_HW_LOCK( sc );
+    if ( sc->uart == BRL1_LOCALUART )
+	lock_console(nasid);
 
     WRITE_L1_UART_REG( nasid, REG_LCR, LCR_DLAB );
 	uart_delay( UART_DELAY_SPAN );
@@ -271,17 +422,17 @@
     WRITE_L1_UART_REG( nasid, REG_FCR,
 	FCR_FIFOEN | FCR_RxFIFO | FCR_TxFIFO );
 
-    L1_CONS_HW_UNLOCK( sc );
+    if ( sc->uart == BRL1_LOCALUART )
+	unlock_console(nasid);
 }
 
+/* This requires the console lock */
 static void
 uart_intr_enable( l1sc_t *sc, u_char mask )
 {
     u_char lcr_reg, icr_reg;
     nasid_t nasid = sc->nasid;
 
-    L1_CONS_HW_LOCK(sc);
-
     /* make sure that the DLAB bit in the LCR register is 0
      */
     lcr_reg = READ_L1_UART_REG( nasid, REG_LCR );
@@ -293,18 +444,15 @@
     icr_reg = READ_L1_UART_REG( nasid, REG_ICR );
     icr_reg |= mask;
     WRITE_L1_UART_REG( nasid, REG_ICR, icr_reg /*(ICR_RIEN | ICR_TIEN)*/ );
-
-    L1_CONS_HW_UNLOCK(sc);
 }
 
+/* This requires the console lock */
 static void
 uart_intr_disable( l1sc_t *sc, u_char mask )
 {
     u_char lcr_reg, icr_reg;
     nasid_t nasid = sc->nasid;
 
-    L1_CONS_HW_LOCK(sc);
-
     /* make sure that the DLAB bit in the LCR register is 0
      */
     lcr_reg = READ_L1_UART_REG( nasid, REG_LCR );
@@ -316,8 +464,6 @@
     icr_reg = READ_L1_UART_REG( nasid, REG_ICR );
     icr_reg &= mask;
     WRITE_L1_UART_REG( nasid, REG_ICR, icr_reg /*(ICR_RIEN | ICR_TIEN)*/ );
-
-    L1_CONS_HW_UNLOCK(sc);
 }
 
 #define uart_enable_xmit_intr(sc) \
@@ -353,15 +499,9 @@
 	}						\
     }
 
-#ifdef SABLE
-#define RTR_UART_PUTC_TIMEOUT	0
-#define RTR_UART_DELAY_SPAN	0
-#define RTR_UART_INIT_TIMEOUT	0
-#else
 #define RTR_UART_PUTC_TIMEOUT	UART_PUTC_TIMEOUT*10
 #define RTR_UART_DELAY_SPAN	UART_DELAY_SPAN
 #define RTR_UART_INIT_TIMEOUT	UART_INIT_TIMEOUT*10
-#endif
 
 static int
 rtr_uart_putc( l1sc_t *sc )
@@ -370,7 +510,11 @@
     nasid_t nasid = sc->nasid;
     net_vec_t path = sc->uart;
     rtc_time_t expire = rtc_time() + RTR_UART_PUTC_TIMEOUT;
-    
+
+#ifdef FORCE_CONSOLE_NASID
+    /* We need this for the console write path _elscuart_flush() -> brl1_send() */
+    nasid = sc->nasid = 0;
+#endif
     c = (sc->send[sc->sent] & 0xffULL);
     
     while( 1 ) 
@@ -399,6 +543,10 @@
     nasid_t nasid = sc->nasid;
     net_vec_t path = sc->uart;
 
+#ifdef FORCE_CONSOLE_NASID
+    nasid = sc->nasid = 0;
+#endif
+
     READ_RTR_L1_UART_REG( path, nasid, REG_LSR, &regval );
     if( regval & (LSR_RCA | LSR_PARERR | LSR_FRMERR) )
     {
@@ -468,28 +616,6 @@
 
     return 0;
 }
-    
-	
-
-/*********************************************************************
- * locking macros 
- */
-
-#define L1SC_SEND_LOCK(l,pl)						\
-     { if( (l)->uart == BRL1_LOCALUART )				\
-	 (pl) = mutex_spinlock_spl( &((l)->send_lock), spl7 ); }
-
-#define L1SC_SEND_UNLOCK(l,pl)				\
-     { if( (l)->uart == BRL1_LOCALUART )		\
-	 mutex_spinunlock( &((l)->send_lock), (pl)); }
-
-#define L1SC_RECV_LOCK(l,pl)						\
-     { if( (l)->uart == BRL1_LOCALUART )				\
-	 (pl) = mutex_spinlock_spl( &((l)->recv_lock), spl7 ); }
-
-#define L1SC_RECV_UNLOCK(l,pl)				\
-     { if( (l)->uart == BRL1_LOCALUART )		\
-	 mutex_spinunlock( &((l)->recv_lock), (pl)); }
 
 
 /*********************************************************************
@@ -501,60 +627,17 @@
  *
  */
 
-
 #ifdef SPINLOCKS_WORK
-#define SUBCH_LOCK(sc,pl) \
-     (pl) = mutex_spinlock_spl( &((sc)->subch_lock), spl7 )
-#define SUBCH_UNLOCK(sc,pl) \
-     mutex_spinunlock( &((sc)->subch_lock), (pl) )
-
-#define SUBCH_DATA_LOCK(sbch,pl) \
-     (pl) = mutex_spinlock_spl( &((sbch)->data_lock), spl7 )
-#define SUBCH_DATA_UNLOCK(sbch,pl) \
-     mutex_spinunlock( &((sbch)->data_lock), (pl) )
+#define SUBCH_LOCK(sc)			spin_lock_irq( &((sc)->subch_lock) )
+#define SUBCH_UNLOCK(sc)		spin_unlock_irq( &((sc)->subch_lock) )
+#define SUBCH_DATA_LOCK(sbch) 		spin_lock_irq( &((sbch)->data_lock) )
+#define SUBCH_DATA_UNLOCK(sbch)		spin_unlock_irq( &((sbch)->data_lock) )
 #else
-#define SUBCH_LOCK(sc,pl) 
-#define SUBCH_UNLOCK(sc,pl)
-#define SUBCH_DATA_LOCK(sbch,pl)
-#define SUBCH_DATA_UNLOCK(sbch,pl)
-#endif	/* SPINLOCKS_WORK */
-
-/*
- * set a function to be called for subchannel ch in the event of
- * a transmission low-water interrupt from the uart
- */
-void
-subch_set_tx_notify( l1sc_t *sc, int ch, brl1_notif_t func )
-{
-    int pl;
-    L1SC_SEND_LOCK( sc, pl );
-    sc->subch[ch].tx_notify = func;
-    
-    /* some upper layer is asking to be notified of low-water, but if the 
-     * send buffer isn't already in use, we're going to need to get the
-     * interrupts going on the uart...
-     */
-    if( func && !sc->send_in_use )
-	uart_enable_xmit_intr( sc );
-    L1SC_SEND_UNLOCK(sc, pl );
-}
-
-/*
- * set a function to be called for subchannel ch when data is received
- */
-void
-subch_set_rx_notify( l1sc_t *sc, int ch, brl1_notif_t func )
-{
-#ifdef SPINLOCKS_WORK
-    int pl;
+#define SUBCH_LOCK(sc)
+#define SUBCH_UNLOCK(sc)
+#define SUBCH_DATA_LOCK(sbch)
+#define SUBCH_DATA_UNLOCK(sbch)
 #endif
-    brl1_sch_t *subch = &(sc->subch[ch]);
-
-    SUBCH_DATA_LOCK( subch, pl );
-    sc->subch[ch].rx_notify = func;
-    SUBCH_DATA_UNLOCK( subch, pl );
-}
-
 
 
 /* get_myid is an internal function that reads the PI_CPU_NUM
@@ -680,21 +763,18 @@
 /* timeouts */
 #define BRL1_INIT_TIMEOUT	500000
 
-extern l1sc_t * get_elsc( void );
-
 /*
  * brl1_discard_packet is a dummy "receive callback" used to get rid
  * of packets we don't want
  */
 void brl1_discard_packet( l1sc_t *sc, int ch )
 {
-    int pl;
     brl1_sch_t *subch = &sc->subch[ch];
     sc_cq_t *q = subch->iqp;
-    SUBCH_DATA_LOCK( subch, pl );
+    SUBCH_DATA_LOCK( subch );
     q->opos = q->ipos;
-    atomicClearInt( &(subch->packet_arrived), ~((unsigned)0) );
-    SUBCH_DATA_UNLOCK( subch, pl );
+    atomic_clear( &(subch->packet_arrived), ~((unsigned)0) );
+    SUBCH_DATA_UNLOCK( subch );
 }
 
 
@@ -720,18 +800,14 @@
      */
     if( sc->uart == BRL1_LOCALUART ) 
     {
-	CONS_HW_LOCK(1);
 	if( !(sc->fifo_space) && UART_PUTC_READY( sc->nasid ) )
-//	    sc->fifo_space = UART_FIFO_DEPTH;
-	    sc->fifo_space = 1000;
+	    sc->fifo_space = UART_FIFO_DEPTH;
 	
 	while( (sc->sent < sc->send_len) && (sc->fifo_space) ) {
 	    uart_putc( sc );
 	    sc->fifo_space--;
 	    sc->sent++;
 	}
-
-	CONS_HW_UNLOCK(1);
     }
 
     else
@@ -770,7 +846,6 @@
 	    }
 	}
     }
-    
     return sc->sent;
 }
 
@@ -786,20 +861,25 @@
  * until our message has been completely transmitted.
  */
 
-int
+static int
 brl1_send( l1sc_t *sc, char *msg, int len, u_char type_and_subch, int wait )
 {
-    int pl;
     int index;
     int pkt_len = 0;
     unsigned short crc = INIT_CRC;
     char *send_ptr = sc->send;
 
-    L1SC_SEND_LOCK(sc, pl);
+#ifdef BRINGUP
+    /* We want to be sure that we are sending the entire packet before returning */
+    wait = 1;
+#endif
+    if ( sc->uart == BRL1_LOCALUART )
+	lock_console(sc->nasid);
 
     if( sc->send_in_use ) {
 	if( !wait ) {
-	    L1SC_SEND_UNLOCK(sc, pl);
+    	    if ( sc->uart == BRL1_LOCALUART )
+	    	unlock_console(sc->nasid);
 	    return 0; /* couldn't send anything; wait for buffer to drain */
 	}
 	else {
@@ -880,61 +960,12 @@
 	/* enable low-water interrupts so buffer will be drained */
 	uart_enable_xmit_intr(sc);
     }
-    L1SC_SEND_UNLOCK(sc, pl);
+    if ( sc->uart == BRL1_LOCALUART )
+	unlock_console(sc->nasid);
     return len;
 }
 
 
-/* brl1_send_cont is intended to be called as an interrupt service
- * routine.  It sends until the UART won't accept any more characters,
- * or until an error is encountered (in which case we surrender the
- * send buffer and give up trying to send the packet).  Once the
- * last character in the packet has been sent, this routine releases
- * the send buffer and calls any previously-registered "low-water"
- * output routines.
- */
-int
-brl1_send_cont( l1sc_t *sc )
-{
-    int pl;
-    int done = 0;
-    brl1_notif_t callups[BRL1_NUM_SUBCHANS];
-    brl1_notif_t *callup;
-    brl1_sch_t *subch;
-    int index;
-
-    L1SC_SEND_LOCK(sc, pl);
-    brl1_send_chars( sc );
-    done = (sc->sent == sc->send_len);
-    if( done ) {
-
-	sc->send_in_use = 0;
-	uart_disable_xmit_intr(sc);
-
-	/* collect pointers to callups *before* unlocking */
-	subch = sc->subch;
-	callup = callups;
-	for( index = 0; index < BRL1_NUM_SUBCHANS; index++ ) {
-	    *callup = subch->tx_notify;
-	    subch++;
-	    callup++;
-	}
-    }
-    L1SC_SEND_UNLOCK(sc, pl);
-
-    if( done ) {
-	/* call any upper layer that's asked for low-water notification */
-	callup = callups;
-	for( index = 0; index < BRL1_NUM_SUBCHANS; index++ ) {
-	    if( *callup )
-		(*(*callup))( sc, index );
-	    callup++;
-	}
-    }
-    return 0;
-}
-
-
 /* internal function -- used by brl1_receive to read a character 
  * from the uart and check whether errors occurred in the process.
  */
@@ -1039,14 +1070,16 @@
 {
     int result;		/* value to be returned by brl1_receive */
     int c;		/* most-recently-read character	     	*/
-    int pl;		/* priority level for UART receive lock */
     int done;		/* set done to break out of recv loop	*/
     sc_cq_t *q;		/* pointer to queue we're working with	*/
 
     result = BRL1_NO_MESSAGE;
 
-    L1SC_RECV_LOCK( sc, pl );
-    L1_CONS_HW_LOCK( sc );
+#ifdef FORCE_CONSOLE_NASID
+    sc->nasid = 0;
+#endif
+    if ( sc->uart == BRL1_LOCALUART )
+	lock_console(sc->nasid);
 
     done = 0;
     while( !done )
@@ -1171,7 +1204,6 @@
 		unsigned short crc;	/* holds the crc as we calculate it */
 		int i;			/* index variable */
 		brl1_sch_t *subch;      /* subchannel for received packet */
-		int sch_pl;		/* cookie for subchannel lock */
 		brl1_notif_t callup;	/* "data ready" callup */
 
 		/* whatever else may happen, we've seen a flag and we're
@@ -1226,7 +1258,7 @@
 
 		/* get the subchannel and lock it */
 		subch = &(sc->subch[SUBCH( LAST_HDR_GET(sc) )]);
-		SUBCH_DATA_LOCK( subch, sch_pl );
+		SUBCH_DATA_LOCK( subch );
 		
 		/* if this isn't a console packet, we need to record
 		 * a length byte
@@ -1242,16 +1274,16 @@
 		/* notify subchannel owner that there's something
 		 * on the queue for them
 		 */
-		atomicAddInt( &(subch->packet_arrived), 1);
+		atomic_inc(&(subch->packet_arrived));
 		callup = subch->rx_notify;
-		SUBCH_DATA_UNLOCK( subch, sch_pl );
+		SUBCH_DATA_UNLOCK( subch );
 
 		if( callup ) {
-		    L1_CONS_HW_UNLOCK( sc );
-		    L1SC_RECV_UNLOCK( sc, pl );
+		    if ( sc->uart == BRL1_LOCALUART )
+			unlock_console(sc->nasid);
 		    (*callup)( sc, SUBCH(LAST_HDR_GET(sc)) );
-		    L1SC_RECV_LOCK( sc, pl );
-		    L1_CONS_HW_LOCK( sc );
+		    if ( sc->uart == BRL1_LOCALUART )
+			lock_console(sc->nasid);
 		}
 		continue;	/* go back for more! */
 	    }
@@ -1320,8 +1352,8 @@
 	} /* end of switch( STATE_GET(sc) ) */
     } /* end of while(!done) */
     
-    L1_CONS_HW_UNLOCK( sc );
-    L1SC_RECV_UNLOCK(sc, pl);
+    if ( sc->uart == BRL1_LOCALUART )
+	unlock_console(sc->nasid);
 
     return result;
 }	    
@@ -1338,6 +1370,9 @@
     brl1_sch_t *subch;
 
     bzero( sc, sizeof( *sc ) );
+#ifdef FORCE_CONSOLE_NASID
+    nasid = (nasid_t)0;
+#endif
     sc->nasid = nasid;
     sc->uart = uart;
     sc->getc_f = (uart == BRL1_LOCALUART ? uart_getc : rtr_uart_getc);
@@ -1351,9 +1386,9 @@
     /* assign processor TTY channels */
     for( i = 0; i < CPUS_PER_NODE; i++, subch++ ) {
 	subch->use = BRL1_SUBCH_RSVD;
-	subch->packet_arrived = 0;
-	spinlock_init( &(subch->data_lock), NULL );
-	sv_init( &(subch->arrive_sv), SV_FIFO, NULL );
+	subch->packet_arrived = ATOMIC_INIT(0);
+	spin_lock_init( &(subch->data_lock) );
+	sv_init( &(subch->arrive_sv), &(subch->data_lock), SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */ );
 	subch->tx_notify = NULL;
 	/* (for now, drop elscuart packets in the kernel) */
 	subch->rx_notify = brl1_discard_packet;
@@ -1364,9 +1399,9 @@
      * processor's individual TTY channel has been assigned)
      */
     subch->use = BRL1_SUBCH_RSVD;
-    subch->packet_arrived = 0;
-    spinlock_init( &(subch->data_lock), NULL );
-    sv_init( &(subch->arrive_sv), SV_FIFO, NULL );
+    subch->packet_arrived = ATOMIC_INIT(0);
+    spin_lock_init( &(subch->data_lock) );
+    sv_init( &(subch->arrive_sv), &subch->data_lock, SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */ );
     subch->tx_notify = NULL;
     if( sc->uart == BRL1_LOCALUART ) {
 	subch->iqp = kmem_zalloc_node( sizeof(sc_cq_t), KM_NOSLEEP,
@@ -1387,7 +1422,7 @@
      */
     for( ; i < 0x10; i++, subch++ ) {
 	subch->use = BRL1_SUBCH_FREE;
-	subch->packet_arrived = 0;
+	subch->packet_arrived = ATOMIC_INIT(0);
 	subch->tx_notify = NULL;
 	subch->rx_notify = brl1_discard_packet;
 	subch->iqp = &sc->garbage_q;
@@ -1396,7 +1431,7 @@
     /* remaining subchannels are free */
     for( ; i < BRL1_NUM_SUBCHANS; i++, subch++ ) {
 	subch->use = BRL1_SUBCH_FREE;
-	subch->packet_arrived = 0;
+	subch->packet_arrived = ATOMIC_INIT(0);
 	subch->tx_notify = NULL;
 	subch->rx_notify = brl1_discard_packet;
 	subch->iqp = &sc->garbage_q;
@@ -1404,9 +1439,7 @@
 
     /* initialize synchronization structures
      */
-    spinlock_init( &(sc->send_lock), NULL );
-    spinlock_init( &(sc->recv_lock), NULL );
-    spinlock_init( &(sc->subch_lock), NULL );
+    spin_lock_init( &(sc->subch_lock) );
 
     if( sc->uart == BRL1_LOCALUART ) {
 	uart_init( sc, UART_BAUD_RATE );
@@ -1423,146 +1456,46 @@
 	extern int elsc_module_get(l1sc_t *);
 
 	sc->modid = elsc_module_get( sc );
-	sc->modid = 
-	    (sc->modid < 0 ? INVALID_MODULE : sc->modid);
-
+	sc->modid = (sc->modid < 0 ? INVALID_MODULE : sc->modid);
 	sc->verbose = 1;
     }
 }
 
 
-/*********************************************************************
- * These are interrupt-related functions used in the kernel to service
- * the L1.
- */
-
-/*
- * brl1_intrd is the function which is called in a loop by the
- * xthread that services L1 interrupts.
- */
-#ifdef IRIX
-void
-brl1_intrd( struct eframe_s *ep )
-{
-    u_char isr_reg;
-    l1sc_t *sc = get_elsc();
-
-    isr_reg = READ_L1_UART_REG(sc->nasid, REG_ISR);
-
-    while( isr_reg & (ISR_RxRDY | ISR_TxRDY) ) {
-
-	if( isr_reg & ISR_RxRDY ) {
-	    brl1_receive(sc);
-	}
-	if( (isr_reg & ISR_TxRDY) || 
-	    (sc->send_in_use && UART_PUTC_READY(sc->nasid)) ) 
-	{
-	    brl1_send_cont(sc);
-	}
-	isr_reg = READ_L1_UART_REG(sc->nasid, REG_ISR);
-    }
-
-    /* uart interrupts were blocked at bedrock when the interrupt
-     * was initially answered; reenable them now
-     */
-    intr_unblock_bit( sc->intr_cpu, UART_INTR );
-    ep = ep; /* placate the compiler */
-}
-#endif
-
-
-
-/* brl1_intr is called directly from the uart interrupt; after it runs, the
- * interrupt "daemon" xthread is signalled to continue.
- */
-#ifdef IRIX
-void
-brl1_intr( struct eframe_s *ep )
-{
-    /* Disable the UART interrupt, giving the xthread time to respond.
-     * When the daemon (xthread) finishes doing its thing, it will
-     * unblock the interrupt.
-     */
-    intr_block_bit( get_elsc()->intr_cpu, UART_INTR );
-    ep = ep; /* placate the compiler */
-}
-
-
-/* set up uart interrupt handling for this node's uart
- */
-void
-brl1_connect_intr( l1sc_t *sc )
-{
-    cpuid_t last_cpu;
-
-    sc->intr_cpu = nodepda->node_first_cpu;
-
-    if( intr_connect_level(sc->intr_cpu, UART_INTR, INTPEND0_MAXMASK,
-			   (intr_func_t)brl1_intrd, 0, 
-			   (intr_func_t)brl1_intr) )
-	cmn_err(CE_PANIC, "brl1_connect_intr: Can't connect UART interrupt.");
-
-    uart_enable_recv_intr( sc );
-}
-#endif	/* IRIX */
-
-#ifdef SABLE
-/* this function is called periodically to generate fake interrupts
- * and allow brl1_intrd to send/receive characters
- */
-void
-hubuart_service( void )
-{
-    l1sc_t *sc = get_elsc();
-    /* note that we'll lose error state by reading the lsr_reg.
-     * This is probably ok in the frictionless domain of sable.
-     */
-    int lsr_reg;
-    nasid_t nasid = sc->nasid;
-    lsr_reg = READ_L1_UART_REG( nasid, REG_LSR );
-    if( lsr_reg & (LSR_RCA | LSR_XSRE) ) {
-        REMOTE_HUB_PI_SEND_INTR(0, 0, UART_INTR);
-    }
-}
-#endif /* SABLE */
-
-
-/*********************************************************************
- * The following function allows the kernel to "go around" the
- * uninitialized l1sc structure to allow console output during
- * early system startup.
- */
-
 /* These are functions to use from serial_in/out when in protocol
- * mode to send and receive uart control regs.
+ * mode to send and receive uart control regs. These are external
+ * interfaces into the protocol driver.
  */
 void
-brl1_send_control(int offset, int value)
+l1_control_out(int offset, int value)
 {
-	nasid_t nasid = get_nasid();
+	nasid_t nasid = 0; //(get_elsc())->nasid;
 	WRITE_L1_UART_REG(nasid, offset, value); 
 }
 
 int
-brl1_get_control(int offset)
+l1_control_in(int offset)
 {
-	nasid_t nasid = get_nasid();
+	nasid_t nasid = 0; //(get_elsc())->nasid;
 	return(READ_L1_UART_REG(nasid, offset)); 
 }
 
 #define PUTCHAR(ch) \
     { \
-        while( !(READ_L1_UART_REG( nasid, REG_LSR ) & LSR_XHRE) );  \
+        while( (!(READ_L1_UART_REG( nasid, REG_LSR ) & LSR_XHRE)) || \
+                (!(READ_L1_UART_REG( nasid, REG_MSR ) & MSR_CTS)) ); \
         WRITE_L1_UART_REG( nasid, REG_DAT, (ch) ); \
     }
 
 int
-brl1_send_console_packet( char *str, int len )
+l1_serial_out( char *str, int len )
 {
     int sent = len;
     char crc_char;
     unsigned short crc = INIT_CRC;
-    nasid_t nasid = get_nasid();
+    nasid_t nasid = 0; //(get_elsc())->nasid;
+
+    lock_console(nasid);
 
     PUTCHAR( BRL1_FLAG_CH );
     PUTCHAR( BRL1_EVENT | SC_CONS_SYSTEM );
@@ -1598,9 +1531,18 @@
     PUTCHAR( crc_char );
     PUTCHAR( BRL1_FLAG_CH );
 
+    unlock_console(nasid);
     return sent - len;
 }
 
+int
+l1_serial_in(void)
+{
+	static int l1_cons_getc( l1sc_t *sc );
+
+	return(l1_cons_getc(get_elsc()));
+}
+
 
 /*********************************************************************
  * l1_cons functions
@@ -1612,7 +1554,7 @@
  *
  */
 
-int
+static int
 l1_cons_poll( l1sc_t *sc )
 {
     /* in case this gets called before the l1sc_t structure for the module_t
@@ -1623,13 +1565,13 @@
 	return 0;
     }
 
-    if( sc->subch[SC_CONS_SYSTEM].packet_arrived ) {
+    if( atomic_read(&sc->subch[SC_CONS_SYSTEM].packet_arrived) ) {
 	return 1;
     }
 
     brl1_receive( sc );
 
-    if( sc->subch[SC_CONS_SYSTEM].packet_arrived ) {
+    if( atomic_read(&sc->subch[SC_CONS_SYSTEM].packet_arrived) ) {
 	return 1;
     }
     return 0;
@@ -1638,13 +1580,11 @@
 
 /* pull a character off of the system console queue (if one is available)
  */
-int
+static int
 l1_cons_getc( l1sc_t *sc )
 {
     int c;
-#ifdef SPINLOCKS_WORK
-    int pl;
-#endif
+
     brl1_sch_t *subch = &(sc->subch[SC_CONS_SYSTEM]);
     sc_cq_t *q = subch->iqp;
 
@@ -1652,16 +1592,16 @@
 	return 0;
     }
 
-    SUBCH_DATA_LOCK( subch, pl );
+    SUBCH_DATA_LOCK( subch );
     if( cq_empty( q ) ) {
-	subch->packet_arrived = 0;
-	SUBCH_DATA_UNLOCK( subch, pl );
+	atomic_set(&subch->packet_arrived, 0);
+	SUBCH_DATA_UNLOCK( subch );
 	return 0;
     }
     cq_rem( q, c );
     if( cq_empty( q ) )
-	subch->packet_arrived = 0;
-    SUBCH_DATA_UNLOCK( subch, pl );
+	atomic_set(&subch->packet_arrived, 0);
+    SUBCH_DATA_UNLOCK( subch );
 
     return c;
 }
@@ -1672,106 +1612,15 @@
 void
 l1_cons_init( l1sc_t *sc )
 {
-#ifdef SPINLOCKS_WORK
-    int pl;
-#endif
     brl1_sch_t *subch = &(sc->subch[SC_CONS_SYSTEM]);
 
-    SUBCH_DATA_LOCK( subch, pl );
-    subch->packet_arrived = 0;
+    SUBCH_DATA_LOCK( subch );
+    atomic_set(&subch->packet_arrived, 0);
     cq_init( subch->iqp );
-    SUBCH_DATA_UNLOCK( subch, pl );
-}
-
-
-/*
- * Write a message to the L1 on the system console subchannel.
- *
- * Danger: don't use a non-zero value for the wait parameter unless you're
- * someone important (like a kernel error message).
- */
-int
-l1_cons_write( l1sc_t *sc, char *msg, int len, int wait )
-{
-    return( brl1_send( sc, msg, len, (SC_CONS_SYSTEM | BRL1_EVENT), wait ) );
-}
-
-
-/* 
- * Read as many characters from the system console receive queue as are
- * available there (up to avail bytes).
- */
-int
-l1_cons_read( l1sc_t *sc, char *buf, int avail )
-{
-    int pl;
-    int before_wrap, after_wrap;
-    brl1_sch_t *subch = &(sc->subch[SC_CONS_SYSTEM]);
-    sc_cq_t *q = subch->iqp;
-
-    if( !(subch->packet_arrived) )
-	return 0;
-
-    SUBCH_DATA_LOCK( subch, pl );
-    if( q->opos > q->ipos ) {
-	before_wrap = BRL1_QSIZE - q->opos;
-	if( before_wrap >= avail ) {
-	    before_wrap = avail;
-	    after_wrap = 0;
-	}
-	else {
-	    avail -= before_wrap;
-	    after_wrap = q->ipos;
-	    if( after_wrap > avail )
-		after_wrap = avail;
-	}
-    }
-    else {
-	before_wrap = q->ipos - q->opos;
-	if( before_wrap > avail )
-	    before_wrap = avail;
-	after_wrap = 0;
-    }
-
-
-    BCOPY( q->buf + q->opos, buf, before_wrap  );
-    if( after_wrap )
-        BCOPY( q->buf, buf + before_wrap, after_wrap  );
-    q->opos = ((q->opos + before_wrap + after_wrap) % BRL1_QSIZE);
-
-    subch->packet_arrived = 0;
-    SUBCH_DATA_UNLOCK( subch, pl );
-
-    return( before_wrap + after_wrap );
-}
-	
-
-/*
- * Install a callback function for the system console subchannel 
- * to allow an upper layer to be notified when the send buffer 
- * has been emptied.
- */
-void
-l1_cons_tx_notif( l1sc_t *sc, brl1_notif_t func )
-{
-    subch_set_tx_notify( sc, SC_CONS_SYSTEM, func );
-}
-
-
-/*
- * Install a callback function for the system console subchannel
- * to allow an upper layer to be notified when a packet has been
- * received.
- */
-void
-l1_cons_rx_notif( l1sc_t *sc, brl1_notif_t func )
-{
-    subch_set_rx_notify( sc, SC_CONS_SYSTEM, func );
+    SUBCH_DATA_UNLOCK( subch );
 }
 
 
-
-
 /*********************************************************************
  * The following functions and definitions implement the "message"-
  * style interface to the L1 system controller.
@@ -1795,7 +1644,9 @@
 sc_data_ready( l1sc_t *sc, int ch )
 {
     brl1_sch_t *subch = &(sc->subch[ch]);
+    SUBCH_DATA_LOCK( subch );
     sv_signal( &(subch->arrive_sv) );
+    SUBCH_DATA_UNLOCK( subch );
 }
 
 /* sc_open reserves a subchannel to send a request to the L1 (the
@@ -1810,10 +1661,9 @@
      * subchannel assignment.
      */
     int ch;
-    int pl;
     brl1_sch_t *subch;
 
-    SUBCH_LOCK( sc, pl );
+    SUBCH_LOCK( sc );
 
     /* Look for a free subchannel. Subchannels 0-15 are reserved
      * for other purposes.
@@ -1826,17 +1676,17 @@
 
     if( ch == BRL1_NUM_SUBCHANS ) {
         /* there were no subchannels available! */
-        SUBCH_UNLOCK( sc, pl );
+        SUBCH_UNLOCK( sc );
         return SC_NSUBCH;
     }
 
     subch->use = BRL1_SUBCH_RSVD;
-    SUBCH_UNLOCK( sc, pl );
+    SUBCH_UNLOCK( sc );
 
-    subch->packet_arrived = 0;
+    atomic_set(&subch->packet_arrived, 0);
     subch->target = target;
-    sv_init( &(subch->arrive_sv), SV_FIFO, NULL );
-    spinlock_init( &(subch->data_lock), NULL );
+    spin_lock_init( &(subch->data_lock) );
+    sv_init( &(subch->arrive_sv), &(subch->data_lock), SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */);
     subch->tx_notify = NULL;
     subch->rx_notify = sc_data_ready;
     subch->iqp = kmem_zalloc_node( sizeof(sc_cq_t), KM_NOSLEEP,
@@ -1854,27 +1704,28 @@
 sc_close( l1sc_t *sc, int ch )
 {
     brl1_sch_t *subch;
-    int pl;
 
-    SUBCH_LOCK( sc, pl );
+    SUBCH_LOCK( sc );
     subch = &(sc->subch[ch]);
     if( subch->use != BRL1_SUBCH_RSVD ) {
         /* we're trying to close a subchannel that's not open */
         return SC_NOPEN;
     }
 
-    subch->packet_arrived = 0;
+    atomic_set(&subch->packet_arrived, 0);
     subch->use = BRL1_SUBCH_FREE;
 
+    SUBCH_DATA_LOCK( subch );
     sv_broadcast( &(subch->arrive_sv) );
     sv_destroy( &(subch->arrive_sv) );
-    spinlock_destroy( &(subch->data_lock) );
+    SUBCH_DATA_UNLOCK( subch );
+    spin_lock_destroy( &(subch->data_lock) );
 
     ASSERT( subch->iqp && (subch->iqp != &sc->garbage_q) );
     kmem_free( subch->iqp, sizeof(sc_cq_t) );
     subch->iqp = &sc->garbage_q;
 
-    SUBCH_UNLOCK( sc, pl );
+    SUBCH_UNLOCK( sc );
 
     return SC_SUCCESS;
 }
@@ -2248,7 +2099,7 @@
     else {
 	q->opos = ((q->opos + before_wrap) & (BRL1_QSIZE - 1));
     }
-    atomicAddInt( &(subch->packet_arrived), -1 );
+    atomic_dec(&(subch->packet_arrived));
 }
 
 
@@ -2263,7 +2114,6 @@
 int
 sc_recv_poll( l1sc_t *sc, int ch, char *msg, int *len, uint64_t block )
 {
-    int pl;             /* lock cookie */
     int is_msg = 0;
     brl1_sch_t *subch = &(sc->subch[ch]);
 
@@ -2278,7 +2128,7 @@
         /* kick the next lower layer and see if it pulls anything in
          */
 	brl1_receive( sc );
-	is_msg = subch->packet_arrived;
+	is_msg = atomic_read(&subch->packet_arrived);
 
     } while( block && !is_msg && (rtc_time() < exp_time) );
 
@@ -2287,9 +2137,9 @@
 	return( SC_NMSG );
     }
 
-    SUBCH_DATA_LOCK( subch, pl );
+    SUBCH_DATA_LOCK( subch );
     subch_pull_msg( subch, msg, len );
-    SUBCH_DATA_UNLOCK( subch, pl );
+    SUBCH_DATA_UNLOCK( subch );
 
     return( SC_SUCCESS );
 }
@@ -2305,17 +2155,16 @@
 int
 sc_recv_intr( l1sc_t *sc, int ch, char *msg, int *len, uint64_t block )
 {
-    int pl;             /* lock cookie */
     int is_msg = 0;
     brl1_sch_t *subch = &(sc->subch[ch]);
 
     do {
-	SUBCH_DATA_LOCK(subch, pl);
-	is_msg = subch->packet_arrived;
+	SUBCH_DATA_LOCK(subch);
+	is_msg = atomic_read(&subch->packet_arrived);
 	if( !is_msg && block ) {
 	    /* wake me when you've got something */
 	    subch->rx_notify = sc_data_ready;
-	    sv_wait( &(subch->arrive_sv), 0, &(subch->data_lock), pl );
+	    sv_wait( &(subch->arrive_sv), 0, 0);
 	    if( subch->use == BRL1_SUBCH_FREE ) {
 		/* oops-- somebody closed our subchannel while we were
 		 * sleeping!
@@ -2329,12 +2178,12 @@
 
     if( !is_msg ) {
 	/* no message and we didn't care to wait for one */
-	SUBCH_DATA_UNLOCK( subch, pl );
+	SUBCH_DATA_UNLOCK( subch );
 	return( SC_NMSG );
     }
 
     subch_pull_msg( subch, msg, len );
-    SUBCH_DATA_UNLOCK( subch, pl );
+    SUBCH_DATA_UNLOCK( subch );
 
     return( SC_SUCCESS );
 }
@@ -2388,12 +2237,12 @@
     }
     
     /* block on sc_recv_* */
-#ifdef notyet
+#ifdef LATER
     if( sc->uart == BRL1_LOCALUART ) {
 	return( sc_recv_intr( sc, ch, resp, len, __WAIT_RECV ) );
     }
     else
-#endif
+#endif	/* LATER */
     {
 	return( sc_recv_poll( sc, ch, resp, len, __WAIT_RECV ) );
     }
@@ -2438,12 +2287,12 @@
 {
     brl1_sch_t *subch = &(sc->subch[ch]);
 
-    if( subch->packet_arrived )
+    if( atomic_read(&subch->packet_arrived) )
 	return 1;
 
     brl1_receive( sc );
 
-    if( subch->packet_arrived )
+    if( atomic_read(&subch->packet_arrived) )
 	return 1;
 
     return 0;
@@ -2461,6 +2310,9 @@
 /* sc_dispatch_env_event handles events sent from the system control
  * network's environmental monitor tasks.
  */
+
+#ifdef LINUX_KERNEL_THREADS
+
 static void
 sc_dispatch_env_event( uint code, int argc, char *args, int maxlen )
 {
@@ -2512,18 +2364,16 @@
 	for( ;
 	     i < j && ((args[i] == 0xd) || (args[i] == 0xa));
 	     i++ );
-	
-	/* write the event to syslog */
-#ifdef IRIX
-	cmn_err_tag( ESPcode, CE_WARN, &(args[i]) );
-#endif
     }
 }
+#endif	/* LINUX_KERNEL_THREADS */
 
 
 /* sc_event waits for events to arrive from the system controller, and
  * prints appropriate messages to the syslog.
  */
+
+#ifdef LINUX_KERNEL_THREADS
 static void
 sc_event( l1sc_t *sc, int ch )
 {
@@ -2544,7 +2394,7 @@
 	 */
 	result = sc_recv_intr( sc, ch, event, &event_len, 1 );
 	if( result != SC_SUCCESS ) {
-	    cmn_err( CE_WARN, "Error receiving sysctl event on nasid %d\n",
+	    PRINT_WARNING("Error receiving sysctl event on nasid %d\n",
 		     sc->nasid );
 	}
 	else {
@@ -2588,13 +2438,13 @@
 	
     }			
 }
+#endif	/* LINUX_KERNEL_THREADS */
 
 /* sc_listen sets up a service thread to listen for incoming events.
  */
 void
 sc_listen( l1sc_t *sc )
 {
-    int pl;
     int result;
     brl1_sch_t *subch;
 
@@ -2602,24 +2452,26 @@
     int         len;    /* length of message being sent */
     int         ch;     /* system controller subchannel used */
 
+#ifdef LINUX_KERNEL_THREADS
     extern int msc_shutdown_pri;
+#endif
 
     /* grab the designated "event subchannel" */
-    SUBCH_LOCK( sc, pl );
+    SUBCH_LOCK( sc );
     subch = &(sc->subch[BRL1_EVENT_SUBCH]);
     if( subch->use != BRL1_SUBCH_FREE ) {
-	SUBCH_UNLOCK( sc, pl );
-	cmn_err( CE_WARN, "sysctl event subchannel in use! "
+	SUBCH_UNLOCK( sc );
+	PRINT_WARNING("sysctl event subchannel in use! "
 		 "Not monitoring sysctl events.\n" );
 	return;
     }
     subch->use = BRL1_SUBCH_RSVD;
-    SUBCH_UNLOCK( sc, pl );
+    SUBCH_UNLOCK( sc );
 
-    subch->packet_arrived = 0;
+    atomic_set(&subch->packet_arrived, 0);
     subch->target = BRL1_LOCALUART;
-    sv_init( &(subch->arrive_sv), SV_FIFO, NULL );
-    spinlock_init( &(subch->data_lock), NULL );
+    spin_lock_init( &(subch->data_lock) );
+    sv_init( &(subch->arrive_sv), &(subch->data_lock), SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */);
     subch->tx_notify = NULL;
     subch->rx_notify = sc_data_ready;
     subch->iqp = kmem_zalloc_node( sizeof(sc_cq_t), KM_NOSLEEP,
@@ -2670,7 +2522,7 @@
 	
 err_return:
     /* there was a problem; complain */
-    cmn_err( CE_WARN, "failed to set sysctl event-monitoring subchannel.  "
+    PRINT_WARNING("failed to set sysctl event-monitoring subchannel.  "
 	     "Sysctl events will not be monitored.\n" );
 }
 
@@ -2825,7 +2677,7 @@
 int
 _elscuart_readc( l1sc_t *sc )
 {
-    int c, pl;
+    int c;
     sc_cq_t *q;
     brl1_sch_t *subch;
 
@@ -2833,32 +2685,32 @@
 	subch = &(sc->subch[ SC_CONS_SYSTEM ]);
 	q = subch->iqp;
 	
-	SUBCH_DATA_LOCK( subch, pl );
+	SUBCH_DATA_LOCK( subch );
         if( !cq_empty( q ) ) {
             cq_rem( q, c );
 	    if( cq_empty( q ) ) {
-		subch->packet_arrived = 0;
+		atomic_set(&subch->packet_arrived, 0);
 	    }
-	    SUBCH_DATA_UNLOCK( subch, pl );
+	    SUBCH_DATA_UNLOCK( subch );
             return c;
         }
-	SUBCH_DATA_UNLOCK( subch, pl );
+	SUBCH_DATA_UNLOCK( subch );
     }
 
     subch = &(sc->subch[ L1_ELSCUART_SUBCH(get_myid()) ]);
     q = subch->iqp;
 
-    SUBCH_DATA_LOCK( subch, pl );
+    SUBCH_DATA_LOCK( subch );
     if( cq_empty( q ) ) {
-	SUBCH_DATA_UNLOCK( subch, pl );
+	SUBCH_DATA_UNLOCK( subch );
         return -1;
     }
 
     cq_rem( q, c );
     if( cq_empty ( q ) ) {
-	subch->packet_arrived = 0;
+	atomic_set(&subch->packet_arrived, 0);
     }
-    SUBCH_DATA_UNLOCK( subch, pl );
+    SUBCH_DATA_UNLOCK( subch );
 
     return c;
 }
@@ -2918,6 +2770,7 @@
 #else
     char ver[BRL1_QSIZE];
     extern int elsc_version( l1sc_t *, char * );
+
     if ( IS_RUNNING_ON_SIMULATOR() )
     	return 0;
     return( elsc_version(sc, ver) >= 0 );
@@ -2932,43 +2785,13 @@
 void
 _elscuart_init( l1sc_t *sc )
 {
-    int pl;
     brl1_sch_t *subch = &sc->subch[L1_ELSCUART_SUBCH(get_myid())];
 
-    SUBCH_DATA_LOCK(subch, pl);
+    SUBCH_DATA_LOCK(subch);
 
-    subch->packet_arrived = 0;
+    atomic_set(&subch->packet_arrived, 0);
     cq_init( subch->iqp );
     cq_init( &sc->oq[MAP_OQ(L1_ELSCUART_SUBCH(get_myid()))] );
 
-    SUBCH_DATA_UNLOCK(subch, pl);
-}
-
-
-#ifdef IRIX
-
-/* elscuart_syscon_listen causes the processor on which it's
- * invoked to "listen" to the system console subchannel (that
- * is, subchannel 4) for console input.
- */
-void
-elscuart_syscon_listen( l1sc_t *sc )
-{
-    int pl;
-    brl1_sch_t *subch = &(sc->subch[SC_CONS_SYSTEM]);
-
-    /* if we're already listening, don't bother */
-    if( sc->cons_listen )
-        return;
-
-    SUBCH_DATA_LOCK( subch, pl );
-
-    subch->use = BRL1_SUBCH_RSVD;
-    subch->packet_arrived = 0;
-
-    SUBCH_DATA_UNLOCK( subch, pl );
-
-
-    sc->cons_listen = 1;
+    SUBCH_DATA_UNLOCK(subch);
 }
-#endif	/* IRIX */
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/l1_command.c linux/arch/ia64/sn/io/l1_command.c
--- v2.4.3/linux/arch/ia64/sn/io/l1_command.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/l1_command.c	Thu Apr  5 12:51:47 2001
@@ -18,7 +18,6 @@
 #include <asm/sn/labelcl.h>
 #include <asm/sn/eeprom.h>
 #include <asm/sn/ksys/i2c.h>
-#include <asm/sn/cmn_err.h>
 #include <asm/sn/router.h>
 #include <asm/sn/module.h>
 #include <asm/sn/ksys/l1.h>
@@ -68,7 +67,6 @@
 
 #define SC_COMMAND sc_command
 
-
 /*
  * elsc_init
  *
@@ -206,6 +204,7 @@
     return -1;
 }
 
+
 /*
  * Command Set
  */
@@ -312,6 +311,7 @@
     return 0;
 }
 
+
 /*
  * elsc_rack_bay_get fills in the two int * arguments with the
  * rack number and bay number of the L1 being addressed
@@ -447,8 +447,9 @@
 
     /* construct module ID from rack and slot info */
 
-    if ((ret = elsc_rack_bay_type_get(e, &rnum, &bay, &bricktype)) < 0)
+    if ((ret = elsc_rack_bay_type_get(e, &rnum, &bay, &bricktype)) < 0) {
 	return ret;
+    }
 
     /* report unset location info. with a special, otherwise invalid modid */
     if (rnum == 0 && bay == 0)
@@ -935,6 +936,7 @@
     return cbrick_uid_get( e->nasid, nic );
 }
 
+
 int _elsc_hbt(elsc_t *e, int ival, int rdly)
 {
     e = e;
@@ -958,11 +960,12 @@
 
     /* fill in msg with the opcode & params */
     bzero( msg, BRL1_QSIZE );
-    subch = sc_open( sc, L1_ADDR_LOCAL );
 
-    L1_BUILD_ADDR( &target, compt, rack, bay, L1_ADDR_TASK_CMD );
+    L1_BUILD_ADDR( &target, compt, rack, bay, 0 );
+    subch = sc_open( sc, target );
+
     if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE,
-				 target, L1_REQ_EXEC_CMD, 2,
+				 L1_ADDR_TASK_CMD, L1_REQ_EXEC_CMD, 2,
 				 L1_ARG_ASCII, cmd )) < 0 )
     {
 	sc_close( sc, subch );
@@ -970,7 +973,7 @@
     }
 		   
     /* send the request to the L1 */
-    if( sc_command( sc, subch, msg, msg, &len ) < 0 )
+    if( SC_COMMAND( sc, subch, msg, msg, &len ) < 0 )
     {
 	sc_close( sc, subch );
 	return( ELSC_ERROR_CMD_SEND );
@@ -988,6 +991,38 @@
     return 0;
 }
 
+/*
+ * sc_power_down
+ *
+ * Shuts down the c-brick associated with sc, and any attached I/O bricks
+ * or other c-bricks (won't go through r-bricks).
+ */
+
+int sc_power_down(l1sc_t *sc)
+{
+    return sc_command_interp( sc, L1_ADDR_TYPE_L1, L1_ADDR_RACK_LOCAL, 
+			      L1_ADDR_BAY_LOCAL, "* pwr d" );
+}
+
+
+/*
+ * sc_power_down_all
+ *
+ * Works similarly to sc_power_down, except that the request is sent to the
+ * closest L2 and EVERYBODY gets turned off.
+ */
+
+int sc_power_down_all(l1sc_t *sc)
+{
+    if( nodepda->num_routers > 0 ) {
+	return sc_command_interp( sc, L1_ADDR_TYPE_L2, L1_ADDR_RACK_LOCAL, 
+				  L1_ADDR_BAY_LOCAL, "* pwr d" );
+    }
+    else {
+	return sc_power_down( sc );
+    }
+}
+
 
 /*
  * Routines for reading the R-brick's L1
@@ -1115,10 +1150,6 @@
     if ((ret = iobrick_rack_bay_type_get(sc, &rnum, &bay, &brick_type)) < 0)
         return ret;
 
-    /* report unset location info. with a special, otherwise invalid modid */
-    if (rnum == 0 && bay == 0)
-        return MODULE_NOT_SET;
-
     if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
         return ELSC_ERROR_MODULE;
 
@@ -1203,28 +1234,101 @@
  */
 
 int
-iobrick_pci_slot_pwr( l1sc_t *sc, int bus, int slot, int up )
+iobrick_pci_pwr( l1sc_t *sc, int bus, int slot, int req_code )
 {
-    char cmd[BRL1_QSIZE];
-    unsigned rack, bay, brick_type;
-    if( iobrick_rack_bay_type_get( sc, &rack, &bay, &brick_type ) < 0 )
+#if 0 /* The "bedrock request" method of performing this function
+       * seems to be broken in the L1, so for now use the command-
+       * interpreter method
+       */
+
+    char	msg[BRL1_QSIZE];
+    int		len;    /* length of message being sent */
+    int		subch;  /* system controller subchannel used */
+
+    /* fill in msg with the opcode & params */
+    bzero( msg, BRL1_QSIZE );
+    subch = sc_open( sc, L1_ADDR_LOCALIO );
+
+    if( (len = sc_construct_msg( sc, subch, msg, BRL1_QSIZE,
+				 L1_ADDR_TASK_GENERAL,
+				 req_code, 4,
+				 L1_ARG_INT, bus,
+				 L1_ARG_INT, slot )) < 0 )
+    {
+	sc_close( sc, subch );
+	return( ELSC_ERROR_CMD_ARGS );
+    }
+
+    /* send the request to the L1 */
+    if( SC_COMMAND(sc, subch, msg, msg, &len ) < 0 )
+    {
+	sc_close( sc, subch );
 	return( ELSC_ERROR_CMD_SEND );
-    sprintf( cmd, "pci %d %d %s", bus, slot,
-	     (up ? "u" : "d") );
-    return( sc_command_interp
-	    ( sc, L1_ADDR_TYPE_L1, rack, bay, cmd ) );
+    }
+
+    /* free up subchannel */
+    sc_close( sc, subch );
+
+    /* check response */
+    if( sc_interpret_resp( msg, 0 ) < 0 )
+    {
+	return( ELSC_ERROR_RESP_FORMAT );
+    }
+
+    return 0;
+
+#else
+    char cmd[64];
+    char *fxn;
+
+    switch( req_code )
+    {
+    case L1_REQ_PCI_UP:
+	fxn = "u";
+	break;
+    case L1_REQ_PCI_DOWN:
+	fxn = "d";
+	break;
+    case L1_REQ_PCI_RESET:
+	fxn = "rst";
+	break;
+    default:
+	return( ELSC_ERROR_CMD_ARGS );
+    }
+
+    if( slot == -1 ) 
+	sprintf( cmd, "pci %d %s", bus, fxn );
+    else
+        sprintf( cmd, "pci %d %d %s", bus, slot, fxn );
+	
+    return sc_command_interp( sc, L1_ADDR_TYPE_IOBRICK,
+	L1_ADDR_RACK_LOCAL, L1_ADDR_BAY_LOCAL, cmd );
+#endif
+}
+				 
+int
+iobrick_pci_slot_pwr( l1sc_t *sc, int bus, int slot, int up )
+{
+    return iobrick_pci_pwr( sc, bus, slot, up );
 }
 
 int
 iobrick_pci_bus_pwr( l1sc_t *sc, int bus, int up )
 {
-    char cmd[BRL1_QSIZE];
-    unsigned rack, bay, brick_type;
-    if( iobrick_rack_bay_type_get( sc, &rack, &bay, &brick_type ) < 0 )
-	return( ELSC_ERROR_CMD_SEND );
-    sprintf( cmd, "pci %d %s", bus, (up ? "u" : "d") );
-    return( sc_command_interp
-	    ( sc, L1_ADDR_TYPE_L1, rack, bay, cmd ) );
+    return iobrick_pci_pwr( sc, bus, -1, up );
+}
+
+
+int
+iobrick_pci_slot_rst( l1sc_t *sc, int bus, int slot )
+{
+    return iobrick_pci_pwr( sc, bus, slot, L1_REQ_PCI_RESET );
+}
+
+int
+iobrick_pci_bus_rst( l1sc_t *sc, int bus )
+{
+    return iobrick_pci_pwr( sc, bus, -1, L1_REQ_PCI_RESET );
 }
 
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/labelcl.c linux/arch/ia64/sn/io/labelcl.c
--- v2.4.3/linux/arch/ia64/sn/io/labelcl.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/labelcl.c	Thu Apr  5 12:51:47 2001
@@ -286,7 +286,7 @@
 		if (!strcmp(info_name, old_label_list[i].name)) {
 			/* Not allowed to add duplicate labelled info names. */
 			kfree(new_label_list);
-			printk("labelcl_info_add_LBL: Duplicate label name %s for vertex 0x%p\n", info_name, de);
+			printk(KERN_WARNING "labelcl_info_add_LBL: Duplicate label name %s for vertex 0x%p\n", info_name, de);
 			return(-1);
 		}
 		new_label_list[i] = old_label_list[i]; /* structure copy */
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/mem_refcnt.c linux/arch/ia64/sn/io/mem_refcnt.c
--- v2.4.3/linux/arch/ia64/sn/io/mem_refcnt.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/mem_refcnt.c	Thu Apr 12 12:16:35 2001
@@ -9,7 +9,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/invent.h>
 #include <asm/sn/hcl.h>
@@ -58,15 +57,8 @@
 mem_refcnt_open(devfs_handle_t *devp, mode_t oflag, int otyp, cred_t *crp)
 {
         cnodeid_t node;
-#ifndef CONFIG_IA64_SGI_SN1
-	extern int numnodes;
-#endif
-        
-        ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(*devp) == HUBSPC_REFCOUNTERS );
 
-        if (!cap_able(CAP_MEMORY_MGT)) {
-                return (EPERM);
-        }
+        ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(*devp) == HUBSPC_REFCOUNTERS );
 
         node = master_node_get(*devp);
 
@@ -97,9 +89,6 @@
         int errcode;
         char* buffer;
         size_t blen;
-#ifndef CONFIG_IA64_SGI_SN1
-	extern int numnodes;
-#endif
         
         ASSERT( (hubspc_subdevice_t)(ulong)device_info_get(dev) == HUBSPC_REFCOUNTERS );
 
@@ -186,7 +175,7 @@
                 
                 rcb.rcb_cnodeid = node;
                 rcb.rcb_granularity = MD_PAGE_SIZE;
-#ifdef notyet
+#ifdef LATER
                 rcb.rcb_hw_counter_max = MIGR_COUNTER_MAX_GET(node);
                 rcb.rcb_diff_threshold = MIGR_THRESHOLD_DIFF_GET(node);
 #endif
@@ -209,7 +198,7 @@
                 ASSERT(nslots <= MAX_MEM_SLOTS);
                 for (s = 0; s < nslots; s++) {
                         slot[s].base = (uint64_t)ctob(slot_getbasepfn(node, s));
-#ifdef notyet
+#ifdef LATER
                         slot[s].size  = (uint64_t)ctob(slot_getsize(node, s));
 #else
                         slot[s].size  = (uint64_t)1;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/ml_SN_init.c linux/arch/ia64/sn/io/ml_SN_init.c
--- v2.4.3/linux/arch/ia64/sn/io/ml_SN_init.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/ml_SN_init.c	Thu Apr  5 12:51:47 2001
@@ -45,25 +45,8 @@
 
 extern xwidgetnum_t hub_widget_id(nasid_t);
 
-#ifndef CONFIG_IA64_SGI_IO
-#if defined (IP27)
-short		cputype = CPU_IP27;
-#elif defined (IP33)
-short		cputype = CPU_IP33;
-#elif defined (IP35)
-short		cputype = CPU_IP35;
-#else
-#error <BOMB! define new cputype here >
-#endif
-#endif /* CONFIG_IA64_SGI_IO */
-
 static int	fine_mode = 0;
 
-#ifndef CONFIG_IA64_SGI_IO
-/* Global variables */
-pdaindr_t	pdaindr[MAXCPUS];
-#endif
-
 static cnodemask_t	hub_init_mask;	/* Mask of cpu in a node doing init */
 static volatile cnodemask_t hub_init_done_mask;
 					/* Node mask where we wait for
@@ -101,7 +84,7 @@
 		master_nasid = get_nasid();
 		set_master_bridge_base();
 		FIXME("mlreset: Enable when we support ioc3 ..");
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 		if (get_console_nasid() == master_nasid) 
 			/* Set up the IOC3 */
 			ioc3_mlreset((ioc3_cfg_t *)KL_CONFIG_CH_CONS_INFO(master_nasid)->config_base,
@@ -113,7 +96,7 @@
 		nvram_baseinit();
 
 		fine_mode = is_fine_dirmode();
-#endif /* CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 
 		/* We're the master processor */
 		master_procid = smp_processor_id();
@@ -125,7 +108,7 @@
 		 */
 		ASSERT_ALWAYS(master_nasid == get_nasid());
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 
 	/*
 	 * Activate when calias is implemented.
@@ -155,7 +138,7 @@
 				((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) |
 				(0 << IIO_ITTE_WIDGET_SHIFT)));
 		}
-#endif /* CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 
 		/* Set up the hub initialization mask and init the lock */
 		CNODEMASK_CLRALL(hub_init_mask);
@@ -169,7 +152,7 @@
 		/* Initialize Hub Pseudodriver Management */
 		hubdev_init();
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 		/*
 		 * Our IO system doesn't require cache writebacks.  Set some
 		 * variables appropriately.
@@ -192,7 +175,7 @@
                  * keep redundant PROM code in memory.
                  */
 		he_arcs_set_vectors();
-#endif /* CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 
 	} else { /* slave != 0 */
 		/*
@@ -216,8 +199,10 @@
 
 	extern void router_map_init(nodepda_t *);
 	extern void router_queue_init(nodepda_t *,cnodeid_t);
+	extern void intr_init_vecblk(nodepda_t *, cnodeid_t, int);
+
 #if defined(DEBUG)
-	extern lock_t		intr_dev_targ_map_lock;
+	extern spinlock_t	intr_dev_targ_map_lock;
 	extern uint64_t 	intr_dev_targ_map_size;
 
 	/* Initialize the lock to access the device - target cpu mapping
@@ -229,7 +214,7 @@
 		 * There is always a cnode 0 present.
 		 */
 		intr_dev_targ_map_size = 0;
-		init_spinlock(&intr_dev_targ_map_lock,"dtmap_lock",0);
+		spin_lock_init(&intr_dev_targ_map_lock);
 	}
 #endif	/* DEBUG */
 	/* Allocate per-node platform-dependent data */
@@ -241,8 +226,6 @@
 	hubinfo->h_cnodeid = node;
 	hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node);
 
-	printk("init_platform_nodepda: hubinfo 0x%p, &hubinfo->h_crblock 0x%p\n", hubinfo, &hubinfo->h_crblock);
-
 	spin_lock_init(&hubinfo->h_crblock);
 
 	hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid);
@@ -265,21 +248,18 @@
 	for (sn=0; sn<NUM_SUBNODES; sn++) {
 		SNPDA(npda,sn)->prof_count = 0;
 		SNPDA(npda,sn)->next_prof_timeout = 0;
-// ajm
-#ifndef CONFIG_IA64_SGI_IO
 		intr_init_vecblk(npda, node, sn);
-#endif
 	}
 
 	npda->vector_unit_busy = 0;
 
 	spin_lock_init(&npda->vector_lock);
-	init_MUTEX_LOCKED(&npda->xbow_sema); /* init it locked? */
+	mutex_init_locked(&npda->xbow_sema); /* init it locked? */
 	spin_lock_init(&npda->fprom_lock);
 
 	spin_lock_init(&npda->node_utlbswitchlock);
 	npda->ni_error_print = 0;
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	if (need_utlbmiss_patch) {
 		npda->node_need_utlbmiss_patch = 1;
 		npda->node_utlbmiss_patched = 1;
@@ -299,7 +279,7 @@
 		npda->nasid_mask[nasid / 8] |= (1 << nasid % 8);
 	}
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	npda->node_first_cpu = get_cnode_cpu(node);
 #endif
 
@@ -324,7 +304,7 @@
 	 * may not be guaranteed shared memory at that time
 	 * which precludes depending on a global dump stack
 	 */
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	npda->dump_stack = (uint64_t *)kmem_zalloc_node(DUMP_STACK_SIZE,VM_NOSLEEP,
 							  node);
 	ASSERT_ALWAYS(npda->dump_stack);
@@ -334,7 +314,7 @@
 	 * both the cpus on a node to proceed with nmi
 	 * handling.
 	 */
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	npda->dump_count = 0;
 
 	/* Setup the (module,slot) --> nic mapping for all the routers
@@ -356,7 +336,7 @@
 		npda->node_bte_info[i] = (bteinfo_t *)NULL;
 	}
 #endif
-#endif /* CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 }
 
 /* XXX - Move the interrupt stuff to intr.c ? */
@@ -369,13 +349,15 @@
 void init_platform_pda(cpuid_t cpu)
 {
 	hub_intmasks_t *intmasks;
+#ifdef	LATER
 	cpuinfo_t cpuinfo;
+#endif
 	int i;
 	cnodeid_t	cnode;
 	synergy_da_t	*sda;
 	int	which_synergy;
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	/* Allocate per-cpu platform-dependent data */
 	cpuinfo = (cpuinfo_t)kmem_alloc_node(sizeof(struct cpuinfo_s), GFP_ATOMIC, cputocnode(cpu));
 	ASSERT_ALWAYS(cpuinfo);
@@ -390,7 +372,7 @@
 	// intmasks = &ppda->p_intmasks;
 	intmasks = &sda->s_intmasks;
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	ASSERT_ALWAYS(&ppda->p_nodepda);
 #endif
 
@@ -400,15 +382,15 @@
 
 	/* Set up pointer to the vector block in the nodepda. */
 	/* (Cant use SUBNODEPDA - not working yet) */
-	intmasks->dispatch0 = &Nodepdaindr[cnode]->snpda[cputosubnode(cpu)].intr_dispatch0;
-	intmasks->dispatch1 = &Nodepdaindr[cnode]->snpda[cputosubnode(cpu)].intr_dispatch1;
+	intmasks->dispatch0 = &Nodepdaindr[cnode]->snpda[cpuid_to_subnode(cpu)].intr_dispatch0;
+	intmasks->dispatch1 = &Nodepdaindr[cnode]->snpda[cpuid_to_subnode(cpu)].intr_dispatch1;
 
 	/* Clear INT_PEND1 masks. */
 	for (i = 0; i < N_INTPEND1_MASKS; i++)
 		intmasks->intpend1_masks[i] = 0;
 
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	/* Don't read the routers unless we're the master. */
 	ppda->p_routertick = 0;
 #endif
@@ -419,7 +401,7 @@
 #error "need protect_hub_calias, protect_nmi_handler_data"
 #endif
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 /*
  * For now, just protect the first page (exception handlers). We
  * may want to protect more stuff later.
@@ -433,13 +415,6 @@
 	for (i = 0; i < MAX_REGIONS; i++) {
 		if (i == nasid_to_region(nasid))
 			continue;
-#ifndef BRINGUP
-		/* Protect the exception handlers. */
-		*(__psunsigned_t *)BDPRT_ENTRY(pa, i) = MD_PROT_NO;
-
-		/* Protect the ARCS SPB. */
-		*(__psunsigned_t *)BDPRT_ENTRY(pa + 4096, i) = MD_PROT_NO;
-#endif
 	}
 }
 
@@ -455,15 +430,12 @@
 	for (i = 0; i < MAX_REGIONS; i++) {
 		if (i == nasid_to_region(nasid))
 			continue;
-#ifndef BRINGUP
-		*(__psunsigned_t *)BDPRT_ENTRY(pa, i) = MD_PROT_NO;
-#endif
 	}
 }
-#endif /* CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 
 
-#ifdef IRIX
+#ifdef LATER
 /*
  * Protect areas of memory that we access uncached by marking them as
  * poisoned so the T5 can't read them speculatively and erroneously
@@ -492,7 +464,7 @@
 				CACHE_ERR_AREA_SIZE, 1);
 #error "SN1 not handled correctly"
 }
-#endif	/* IRIX */
+#endif	/* LATER */
 
 /*
  * per_hub_init
@@ -509,15 +481,10 @@
 	ii_icmr_u_t	ii_icmr;
 	ii_ibcr_u_t	ii_ibcr;
 #endif
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	int i;
 #endif
 
-#ifdef SIMULATED_KLGRAPH
-	compact_to_nasid_node[0] = 0;
-	nasid_to_compact_node[0] = 0;
-	FIXME("per_hub_init: SIMULATED_KLCONFIG: compact_to_nasid_node[0] = 0\n");
-#endif /* SIMULATED_KLGRAPH */
 	nasid = COMPACT_TO_NASID_NODEID(cnode);
 
 	ASSERT(nasid != INVALID_NASID);
@@ -546,15 +513,26 @@
 	if (!done) {
 		npdap = NODEPDA(cnode);
 
+#if defined(CONFIG_IA64_SGI_SYNERGY_PERF)
+		/* initialize per-node synergy perf instrumentation */
+		npdap->synergy_perf_enabled = 0; /* off by default */
+		npdap->synergy_perf_lock = SPIN_LOCK_UNLOCKED;
+		npdap->synergy_perf_freq = SYNERGY_PERF_FREQ_DEFAULT;
+		npdap->synergy_inactive_intervals = 0;
+		npdap->synergy_active_intervals = 0;
+		npdap->synergy_perf_data = NULL;
+		npdap->synergy_perf_first = NULL;
+#endif /* CONFIG_IA64_SGI_SYNERGY_PERF */
+
 		npdap->hub_chip_rev = get_hub_chiprev(nasid);
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 		for (i = 0; i < CPUS_PER_NODE; i++) {
 			cpu = cnode_slice_to_cpuid(cnode, i);
 			if (!cpu_enabled(cpu))
 			    SET_CPU_LEDS(nasid, i, 0xf);
 		}
-#endif /* CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 
 #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) /* SN1 specific */
 
@@ -582,7 +560,6 @@
 #endif /* SN0_HWDEBUG */
 
 
-#ifndef CONFIG_IA64_SGI_IO
 
 		/* Reserve all of the hardwired interrupt levels. */
 		intr_reserve_hardwired(cnode);
@@ -590,6 +567,7 @@
 		/* Initialize error interrupts for this hub. */
 		hub_error_init(cnode);
 
+#ifdef LATER
 		/* Set up correctable memory/directory ECC error interrupt. */
 		install_eccintr(cnode);
 
@@ -599,7 +577,7 @@
 		/* Enable RT clock interrupts */
 		hub_rtc_init(cnode);
 		hub_migrintr_init(cnode); /* Enable migration interrupt */
-#endif
+#endif	/* LATER */
 
 		spin_lock(&hub_mask_lock);
 		CNODEMASK_SETB(hub_init_done_mask, cnode);
@@ -609,9 +587,14 @@
 		/*
 		 * Wait for the other CPU to complete the initialization.
 		 */
-		while (CNODEMASK_TSTB(hub_init_done_mask, cnode) == 0)
+		while (CNODEMASK_TSTB(hub_init_done_mask, cnode) == 0) {
+			/*
+			 * On SNIA64 we should never get here ..
+			 */
+			printk("WARNING: per_hub_init: Should NEVER get here!\n");
 			/* LOOP */
 			;
+		}
 	}
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/ml_SN_intr.c linux/arch/ia64/sn/io/ml_SN_intr.c
--- v2.4.3/linux/arch/ia64/sn/io/ml_SN_intr.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/ml_SN_intr.c	Thu Apr 12 12:16:35 2001
@@ -34,6 +34,8 @@
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/xtalk/xtalk.h>
 #include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/intr.h>
+
 
 #if DEBUG_INTR_TSTAMP_DEBUG
 #include <sys/debug.h>
@@ -65,6 +67,8 @@
 
 extern cnodeid_t master_node_get(devfs_handle_t vhdl);
 
+extern snia_error_intr_handler(int irq, void *devid, struct pt_regs *pt_regs);
+
 
 #define INTR_LOCK(vecblk) \
      (s = mutex_spinlock(&(vecblk)->vector_lock))
@@ -99,7 +103,7 @@
 void
 intr_stray(void *lvl)
 {
-    printk("Stray Interrupt - level %ld to cpu %d", (long)lvl, cpuid());
+    PRINT_WARNING("Stray Interrupt - level %ld to cpu %d", (long)lvl, cpuid());
 }
 
 #if defined(DEBUG)
@@ -119,7 +123,7 @@
 
 intr_dev_targ_map_t 	intr_dev_targ_map[MAX_DEVICES];
 uint64_t		intr_dev_targ_map_size;
-lock_t			intr_dev_targ_map_lock;
+spinlock_t		intr_dev_targ_map_lock;
 
 /* Print out the device - target cpu mapping.
  * This routine is used only in the idbg command
@@ -220,7 +224,7 @@
 
 	    }
 
-	spinlock_init(&vecblk->vector_lock, "ivecb");
+	mutex_spinlock_init(&vecblk->vector_lock);
 
 	vecblk->vector_count = 0;    
 	for (i = 0; i < CPUS_PER_SUBNODE; i++)
@@ -254,7 +258,7 @@
 {
     intr_vecblk_t	*vecblk;
     hub_intmasks_t 	*hub_intmasks;
-    int s;
+    unsigned long s;
     int rv = 0;
     int ip;
     synergy_da_t	*sda;
@@ -283,8 +287,7 @@
     INTR_LOCK(vecblk);
 
     if (bit <= -1) {
-	// bit = 0;
-	bit = 7;  /* First available on SNIA */
+	bit = 0;
 	ASSERT(reserve == II_RESERVE);
 	/* Choose any available level */
 	for (; bit < N_INTPEND_BITS; bit++) {
@@ -449,9 +452,9 @@
 {
     intr_vecblk_t	*vecblk;
     hubreg_t		*intpend_masks;
-    int s;
     int rv = 0;
     int ip;
+    unsigned long s;
 
     ASSERT(bit < N_INTPEND_BITS * 2);
 
@@ -530,7 +533,7 @@
 {
     intr_vecblk_t	*vecblk;
     hubreg_t		*intpend_masks;
-    int s;
+    unsigned long s;
     int rv = 0;
     int ip;
 
@@ -582,8 +585,8 @@
 do_intr_block_bit(cpuid_t cpu, int bit, int block)
 {
 	intr_vecblk_t *vecblk;
-	int s;
 	int ip;
+	unsigned long s;
 	hubreg_t *intpend_masks;
 	volatile hubreg_t mask_value;
 	volatile hubreg_t *mask_reg;
@@ -671,7 +674,6 @@
 		int local_cpu_num;
 
 		cpu = cnode_slice_to_cpuid(cnode, slice);
-		cpu = cpu_logical_id(cpu);
 		if (cpu == CPU_NONE)
 			continue;
 
@@ -711,7 +713,7 @@
 }
 
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 /*
  * Convert a subnode vertex into a (cnodeid, which_subnode) pair.
  * Return 0 on success, non-zero on failure.
@@ -736,7 +738,7 @@
 	return(0); /* success */
 }
 
-#endif /* CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 
 /* Make it easy to identify subnode vertices in the hwgraph */
 void
@@ -755,13 +757,14 @@
 }
 
 
-#ifndef CONFIG_IA64_SGI_IO
 /*
  * Given a device descriptor, extract interrupt target information and
  * choose an appropriate CPU.  Return CPU_NONE if we can't make sense
  * out of the target information.
  * TBD: Should this be considered platform-independent code?
  */
+
+#ifdef	LATER
 static cpuid_t
 intr_target_from_desc(device_desc_t dev_desc, int favor_subnode)
 {
@@ -799,10 +802,10 @@
 cpuchosen:
 	return(cpuid);
 }
-#endif /* CONFIG_IA64_SGI_IO */
+#endif	/* LATER */
 
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 /*
  * Check if we had already visited this candidate cnode
  */
@@ -824,7 +827,7 @@
 	return(visited_cnodes);
 }
 
-#endif /* CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 
 
 
@@ -915,7 +918,7 @@
 {
 	cpuid_t		cpuid;				/* possible intr targ*/
 	cnodeid_t 	candidate;			/* possible canidate */
-#ifndef BRINGUP
+#ifdef LATER
 	cnodeid_t	visited_cnodes[MAX_NASIDS], 	/* nodes seen so far */
 		        center,				/* node we are on */
 		        candidate;			/* possible canidate */
@@ -926,10 +929,10 @@
 							 */
 		        maxradius = physmem_maxradius();
 	void		*rv;
-#endif /* BRINGUP */
+#endif /* LATER */
 	int		which_subnode = SUBNODE_ANY;
 
-#if CONFIG_IA64_SGI_IO /* SN1 + pcibr Addressing Limitation */
+/* SN1 + pcibr Addressing Limitation */
 	{
 	devfs_handle_t pconn_vhdl;
 	pcibr_soft_t pcibr_soft;
@@ -962,9 +965,8 @@
 		}
 	}
 	}
-#endif /* CONFIG_IA64_SGI_IO */
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef	LATER
 	/* 
 	 * If an interrupt target was specified for this
 	 * interrupt allocation, try to use it.
@@ -998,7 +1000,7 @@
 		 */
 
 	}
-#endif  /* CONFIG_IA64_SGI_IO */
+#endif  /* LATER */
 	
 	/* Check if we can find a valid interrupt target candidate on
 	 * the master node for the device.
@@ -1019,7 +1021,7 @@
 			intr_unreserve_level(cpuid, *resp_bit);
 	}
 
-	printk("Cannot target interrupts to closest node(%d): %ld (0x%lx)\n",
+	PRINT_WARNING("Cannot target interrupts to closest node(%d): %ld (0x%lx)\n",
 		master_node_get(dev),(long) owner_dev, (unsigned long)owner_dev);
 
 	/* Fall through into the default algorithm
@@ -1076,10 +1078,11 @@
 #else  /* BRINGUP */
 	{
 	// Do a stupid round-robin assignment of the node.
-		static cnodeid_t last_node = 0;
+		static cnodeid_t last_node = -1;
 
-		if (last_node > numnodes) last_node = 0;
-		for (candidate = last_node; candidate <= numnodes; candidate++) {
+		if (last_node >= numnodes) last_node = 0;
+		for (candidate = last_node + 1; candidate != last_node; candidate++) {
+			if (candidate == numnodes) candidate = 0;
 			cpuid = intr_bit_reserve_test(CPU_NONE,
 					      which_subnode,
 					      candidate,
@@ -1091,18 +1094,18 @@
 
 			if (cpuid != CPU_NONE) {
 				if (cpu_on_subnode(cpuid, which_subnode)) {
-					last_node++;
+					last_node = candidate;
 					return(cpuid);	/* got a valid interrupt target */
 				}
 				else
 					intr_unreserve_level(cpuid, *resp_bit);
 			}
-			last_node++;
 		}
+		last_node = candidate;
 	}
 #endif
 
-	printk("Cannot target interrupts to any close node: %ld (0x%lx)\n",
+	PRINT_WARNING("Cannot target interrupts to any close node: %ld (0x%lx)\n",
 		(long)owner_dev, (unsigned long)owner_dev);
 
 	/* In the worst case try to allocate interrupt bits on the
@@ -1127,7 +1130,7 @@
 			intr_unreserve_level(cpuid, *resp_bit);
 	}
 
-	printk("Cannot target interrupts: %ld (0x%lx)\n",
+	PRINT_WARNING("Cannot target interrupts: %ld (0x%lx)\n",
 		(long)owner_dev, (unsigned long)owner_dev);
 
 	return(CPU_NONE);	/* Should never get here */
@@ -1515,6 +1518,7 @@
 	}
 }
 
+#endif /* BRINGUP */
 
 struct hardwired_intr_s {
 	signed char level;
@@ -1525,17 +1529,9 @@
 	{ INT_PEND0_BASELVL + GFX_INTR_A,	0, 	"Gfx A" },
 	{ INT_PEND0_BASELVL + GFX_INTR_B,	0, 	"Gfx B" },
 	{ INT_PEND0_BASELVL + PG_MIG_INTR,	II_THREADED, "Migration" },
-#if defined(SN1) && !defined(DIRECT_L1_CONSOLE)
 	{ INT_PEND0_BASELVL + UART_INTR,	II_THREADED, "Bedrock/L1" },
-#else
-	{ INT_PEND0_BASELVL + UART_INTR,	0,	"Hub I2C" },
-#endif
 	{ INT_PEND0_BASELVL + CC_PEND_A,	0,	"Crosscall A" },
 	{ INT_PEND0_BASELVL + CC_PEND_B,	0,	"Crosscall B" },
-	{ INT_PEND0_BASELVL + MSC_MESG_INTR,	II_THREADED, "MSC Message" },
-	{ INT_PEND0_BASELVL + CPU_ACTION_A,	0,	"CPU Action A" },
-	{ INT_PEND0_BASELVL + CPU_ACTION_B,	0,	"CPU Action B" },
-	{ INT_PEND1_BASELVL + IO_ERROR_INTR,	II_ERRORINT, "IO Error" },
 	{ INT_PEND1_BASELVL + CLK_ERR_INTR,	II_ERRORINT, "Clock Error" },
 	{ INT_PEND1_BASELVL + COR_ERR_INTR_A,	II_ERRORINT, "Correctable Error A" },
 	{ INT_PEND1_BASELVL + COR_ERR_INTR_B,	II_ERRORINT, "Correctable Error B" },
@@ -1546,13 +1542,11 @@
 	{ INT_PEND1_BASELVL + MSC_PANIC_INTR,	II_ERRORINT, "MSC Panic" },
 	{ INT_PEND1_BASELVL + LLP_PFAIL_INTR_A,	II_ERRORINT, "LLP Pfail WAR" },
 	{ INT_PEND1_BASELVL + LLP_PFAIL_INTR_B,	II_ERRORINT, "LLP Pfail WAR" },
-#ifdef SN1
 	{ INT_PEND1_BASELVL + NACK_INT_A,	0, "CPU A Nack count == NACK_CMP" },
 	{ INT_PEND1_BASELVL + NACK_INT_B,	0, "CPU B Nack count == NACK_CMP" },
 	{ INT_PEND1_BASELVL + LB_ERROR,		0, "Local Block Error" },
 	{ INT_PEND1_BASELVL + XB_ERROR,		0, "Local XBar Error" },
-#endif /* SN1 */	
-	{ -1, 0, (char *)NULL}
+	{ -1, 0, (char *)NULL},
 };
 
 /*
@@ -1567,7 +1561,13 @@
 	int i;
 	char subnode_done[NUM_SUBNODES];
 
-	cpu = cnodetocpu(cnode);
+	// cpu = cnodetocpu(cnode);
+	for (cpu = 0; cpu < smp_num_cpus; cpu++) {
+		if (cpuid_to_cnodeid(cpu) == cnode) {
+			break;
+		}
+	}
+	if (cpu == smp_num_cpus) cpu = CPU_NONE;
 	if (cpu == CPU_NONE) {
 		printk("Node %d has no CPUs", cnode);
 		return;
@@ -1576,7 +1576,7 @@
 	for (i=0; i<NUM_SUBNODES; i++)
 		subnode_done[i] = 0;
 
-	for (; cpu<maxcpus && cpu_enabled(cpu) && cputocnode(cpu) == cnode; cpu++) {
+	for (; cpu<smp_num_cpus && cpu_enabled(cpu) && cpuid_to_cnodeid(cpu) == cnode; cpu++) {
 		int which_subnode = cpuid_to_subnode(cpu);
 		if (subnode_done[which_subnode])
 			continue;
@@ -1594,7 +1594,6 @@
 	}
 }
 
-#endif /* BRINGUP */
 
 /*
  * Check and clear interrupts.
@@ -1612,7 +1611,7 @@
 		for (i = 0; i < N_INTPEND_BITS; i++) {
 			if (bits & (1 << i)) {
 #ifdef INTRDEBUG
-				printk( "Nasid %d interrupt bit %d set in %s",
+				PRINT_WARNING("Nasid %d interrupt bit %d set in %s",
 					nasid, i, name);
 #endif
 				LOCAL_HUB_CLR_INTR(base_level + i);
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/ml_iograph.c linux/arch/ia64/sn/io/ml_iograph.c
--- v2.4.3/linux/arch/ia64/sn/io/ml_iograph.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/ml_iograph.c	Thu Apr 12 12:16:35 2001
@@ -32,6 +32,13 @@
 
 extern int maxnodes;
 
+/* #define IOGRAPH_DEBUG */
+#ifdef IOGRAPH_DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* IOGRAPH_DEBUG */
+
 /* #define PROBE_TEST */
 
 /* At most 2 hubs can be connected to an xswitch */
@@ -44,7 +51,7 @@
  * xswitch vertex is created.
  */
 typedef struct xswitch_vol_s {
-	struct semaphore xswitch_volunteer_mutex;
+	mutex_t xswitch_volunteer_mutex;
 	int		xswitch_volunteer_count;
 	devfs_handle_t	xswitch_volunteer[NUM_XSWITCH_VOLUNTEER];
 } *xswitch_vol_t;
@@ -56,7 +63,7 @@
 	int rc;
 
 	xvolinfo = kmalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL);
-	init_MUTEX(&xvolinfo->xswitch_volunteer_mutex);
+	mutex_init(&xvolinfo->xswitch_volunteer_mutex);
 	xvolinfo->xswitch_volunteer_count = 0;
 	rc = hwgraph_info_add_LBL(xswitch, 
 			INFO_LBL_XSWITCH_VOL,
@@ -78,7 +85,7 @@
 	rc = hwgraph_info_remove_LBL(xswitch, 
 				INFO_LBL_XSWITCH_VOL,
 				(arbitrary_info_t *)&xvolinfo);
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef LATER
 	ASSERT(rc == GRAPH_SUCCESS); rc = rc;
 #endif
 
@@ -97,64 +104,26 @@
 				INFO_LBL_XSWITCH_VOL, 
 				(arbitrary_info_t *)&xvolinfo);
 	if (xvolinfo == NULL) {
-#ifndef CONFIG_IA64_SGI_IO
-	    if (!is_headless_node_vertex(master))
-		cmn_err(CE_WARN, 
-			"volunteer for widgets: vertex %v has no info label",
+#ifdef LATER
+	    if (!is_headless_node_vertex(master)) {
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+		PRINT_WARNING("volunteer for widgets: vertex %v has no info label",
+			xswitch);
+#else
+		PRINT_WARNING("volunteer for widgets: vertex 0x%x has no info label",
 			xswitch);
 #endif
+	    }
+#endif	/* LATER */
 	    return;
 	}
 
-#ifndef CONFIG_IA64_SGI_IO
-	mutex_lock(&xvolinfo->xswitch_volunteer_mutex, PZERO);
-#endif
+	mutex_lock(&xvolinfo->xswitch_volunteer_mutex);
 	ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER);
 	xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master;
 	xvolinfo->xswitch_volunteer_count++;
-#ifndef CONFIG_IA64_SGI_IO
 	mutex_unlock(&xvolinfo->xswitch_volunteer_mutex);
-#endif
-}
-
-#ifndef	BRINGUP
-/* 
- * The "ideal fixed assignment" of 12 IO slots to 4 node slots.
- * At index N is the node slot number of the node board that should
- * ideally control the widget in IO slot N.  Note that if there is
- * only one node board on a given xbow, it will control all of the
- * devices on that xbow regardless of these defaults.
- *
- * 	N1 controls IO slots IO1, IO3, IO5	(upper left)
- * 	N3 controls IO slots IO2, IO4, IO6	(upper right)
- * 	N2 controls IO slots IO7, IO9, IO11	(lower left)
- * 	N4 controls IO slots IO8, IO10, IO12	(lower right)
- *
- * This makes assignments predictable and easily controllable.
- * TBD: Allow administrator to override these defaults.
- */
-static slotid_t ideal_assignment[] = {
-	-1,	/* IO0 -->non-existent */
-	1,	/* IO1 -->N1 */
-	3,	/* IO2 -->N3 */
-	1,	/* IO3 -->N1 */
-	3,	/* IO4 -->N3 */
-	1,	/* IO5 -->N1 */
-	3,	/* IO6 -->N3 */
-	2,	/* IO7 -->N2 */
-	4,	/* IO8 -->N4 */
-	2,	/* IO9 -->N2 */
-	4,	/* IO10-->N4 */
-	2,	/* IO11-->N2 */
-	4	/* IO12-->N4 */
-};
-
-static int
-is_ideal_assignment(slotid_t hubslot, slotid_t ioslot)
-{
-	return(ideal_assignment[ioslot] == hubslot);
 }
-#endif /* ifndef BRINGUP */
 
 extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum);
 
@@ -166,15 +135,12 @@
 static void
 assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv)
 {
+	int curr_volunteer, num_volunteer;
+	xwidgetnum_t widgetnum;
 	xswitch_info_t xswitch_info;
 	xswitch_vol_t xvolinfo = NULL;
-	xwidgetnum_t widgetnum;
-	int curr_volunteer, num_volunteer;
 	nasid_t nasid;
 	hubinfo_t hubinfo;
-#ifndef BRINGUP
-	int xbownum;
-#endif
 
 	hubinfo_get(hubv, &hubinfo);
 	nasid = hubinfo->h_nasid;
@@ -186,13 +152,19 @@
 				INFO_LBL_XSWITCH_VOL, 
 				(arbitrary_info_t *)&xvolinfo);
 	if (xvolinfo == NULL) {
-#ifndef CONFIG_IA64_SGI_IO
-	    if (!is_headless_node_vertex(hubv))
-		cmn_err(CE_WARN, 
-			"assign_widgets_to_volunteers:vertex %v has "
+#ifdef LATER
+	    if (!is_headless_node_vertex(hubv)) {
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+		PRINT_WARNING("assign_widgets_to_volunteers:vertex %v has "
+			" no info label",
+			xswitch);
+#else
+		PRINT_WARNING("assign_widgets_to_volunteers:vertex 0x%x has "
 			" no info label",
 			xswitch);
 #endif
+	    }
+#endif	/* LATER */
 	    return;
 	}
 
@@ -206,10 +178,6 @@
 		xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv);
 	}
 
-#ifndef	BRINGUP
-	xbownum = get_node_crossbow(nasid);
-#endif /* ifndef BRINGUP */
-
 	/*
 	 * TBD: Use administrative information to alter assignment of
 	 * widgets to hubs.
@@ -239,29 +207,12 @@
 				if (nasid == get_console_nasid())
 					goto do_assignment;
 			}
-#ifndef CONFIG_IA64_SGI_IO
-			cmn_err(CE_PANIC,
-				"Nasid == %d, console nasid == %d",
+#ifdef LATER
+			PRINT_PANIC("Nasid == %d, console nasid == %d",
 				nasid, get_console_nasid());
 #endif
 		}
 
-#ifndef	BRINGUP
-		/*
-		 * Try to do the "ideal" assignment if IO slots to nodes.
-		 */
-		for (i=0; i<num_volunteer; i++) {
-			hubv = xvolinfo->xswitch_volunteer[i];
-			hubinfo_get(hubv, &hubinfo);
-			nasid = hubinfo->h_nasid;
-			if (is_ideal_assignment(SLOTNUM_GETSLOT(get_node_slotid(nasid)),
-						SLOTNUM_GETSLOT(get_widget_slotnum(xbownum, widgetnum)))) {
-
-				goto do_assignment;
-				
-			}
-		}
-#endif /* ifndef BRINGUP */
 
 		/*
 		 * Do a round-robin assignment among the volunteer nodes.
@@ -301,13 +252,13 @@
 	for(cnode = 0; cnode < numnodes; cnode++) {
 		nasid = COMPACT_TO_NASID_NODEID(cnode);
 		board = (lboard_t *)KL_CONFIG_INFO(nasid);
-		printk("iograph_early_init: Found board 0x%p\n", board);
+		DBG("iograph_early_init: Found board 0x%p\n", board);
 
 		/* Check out all the board info stored on a node */
 		while(board) {
 			board->brd_graph_link = GRAPH_VERTEX_NONE;
 			board = KLCF_NEXT(board);
-			printk("iograph_early_init: Found board 0x%p\n", board);
+			DBG("iograph_early_init: Found board 0x%p\n", board);
 
 
 		}
@@ -316,7 +267,7 @@
 	hubio_init();
 }
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef LATER
 /* There is an identical definition of this in os/scheduler/runq.c */
 #define INIT_COOKIE(cookie) cookie.must_run = 0; cookie.cpu = PDA_RUNANYWHERE
 /*
@@ -363,12 +314,11 @@
 {
 	restoremustrun(cookie);
 }
-static sema_t io_init_sema;
-
-#endif	/* !CONFIG_IA64_SGI_IO */
-
-struct semaphore io_init_sema;
+#endif	/* LATER */
 
+#ifdef LINUX_KERNEL_THREADS
+static struct semaphore io_init_sema;
+#endif
 
 /*
  * Let boot processor know that we're done initializing our node's IO
@@ -378,9 +328,11 @@
 static void
 io_init_done(cnodeid_t cnodeid,cpu_cookie_t c)
 {
-#ifndef CONFIG_IA64_SGI_IO
 	/* Let boot processor know that we're done. */
+#ifdef LINUX_KERNEL_THREADS
 	up(&io_init_sema);
+#endif
+#ifdef LATER
 	/* This is for the setnoderun done when the io_init thread
 	 * started 
 	 */
@@ -420,17 +372,12 @@
 		 * We're able to read from a widget because our hub's 
 		 * WIDGET_ID was set up earlier.
 		 */
-#ifdef	BRINGUP
 		widgetreg_t widget_id = *(volatile widgetreg_t *)
 			(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
 
-		printk("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id,
+		DBG("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id,
 		(volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) );
 
-#else	/* !BRINGUP */
-		widgetreg_t widget_id = XWIDGET_ID_READ(nasid, 0);
-#endif	/* BRINGUP */
-
 		hwid->part_num = XWIDGET_PART_NUM(widget_id);
 		hwid->rev_num = XWIDGET_REV_NUM(widget_id);
 		hwid->mfg_num = XWIDGET_MFG_NUM(widget_id);
@@ -438,8 +385,6 @@
 		/* TBD: link reset */
 	} else {
 
-		panic("\n\n**** early_probe_for_widget: Hub Vertex 0x%p is DOWN llp_csr_reg 0x%x ****\n\n", hubv, llp_csr_reg);
-
 		hwid->part_num = XWIDGET_PART_NUM_NONE;
 		hwid->rev_num = XWIDGET_REV_NUM_NONE;
 		hwid->mfg_num = XWIDGET_MFG_NUM_NONE;
@@ -499,8 +444,9 @@
 	moduleid_t		module;
 	slotid_t		slot;
 	lboard_t		*board = NULL;
+	char			buffer[16];
 	
-	printk("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum);
+	DBG("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum);
 	/*
 	 * Verify that xswitchv is indeed an attached xswitch.
 	 */
@@ -546,8 +492,8 @@
 		 * but I don't feel like figuring out vhdl right now..
 		 * and I know for a fact the answer is 0x2d000049 
 		 */
-		printk("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).\n");
-		printk("XWIDGET_PART_NUM(0x2d000049)= 0x%x\n", XWIDGET_PART_NUM(0x2d000049));
+		DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).\n");
+		DBG("XWIDGET_PART_NUM(0x2d000049)= 0x%x\n", XWIDGET_PART_NUM(0x2d000049));
 		if (XWIDGET_PART_NUM(0x2d000049)==XXBOW_WIDGET_PART_NUM) {
 #else
 		if (nasid_has_xbridge(nasid)) {
@@ -557,8 +503,18 @@
 				module,
 				KLTYPE_IOBRICK);
 
-			if (board)
-				printk("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type);
+DBG("io_xswitch_widget_init: Board 0x%p\n", board);
+{
+		lboard_t dummy;
+
+			if (board) {
+				DBG("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type);
+			} else {
+				DBG("io_xswitch_widget_init: FIXME did not find IOBOARD\n");
+				board = &dummy;
+			}
+				
+}
 
 			/*
 			 * BRINGUP
@@ -568,11 +524,16 @@
 
 #ifdef SUPPORT_PRINTING_M_FORMAT
 			sprintf(pathname, EDGE_LBL_MODULE "/%M/"
-#else
-			sprintf(pathname, EDGE_LBL_MODULE "/%x/"
-#endif
 				"%cbrick" "/%s/%d",
 				NODEPDA(cnode)->module_id,
+				
+#else
+			memset(buffer, 0, 16);
+			format_module_id(buffer, NODEPDA(cnode)->module_id, MODULE_FORMAT_BRIEF);
+			sprintf(pathname, EDGE_LBL_MODULE "/%s/"
+				"%cbrick" "/%s/%d",
+				buffer,
+#endif
 #ifdef BRINGUP
 
 				(board->brd_type == KLTYPE_IBRICK) ? 'I' :
@@ -584,7 +545,7 @@
 				EDGE_LBL_XTALK, widgetnum);
 		} 
 		
-		printk("io_xswitch_widget_init: path= %s\n", pathname);
+		DBG("io_xswitch_widget_init: path= %s\n", pathname);
 		rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv);
 		
 		ASSERT(rc == GRAPH_SUCCESS);
@@ -612,7 +573,7 @@
 			module 	= NODEPDA(cnode)->module_id;
 
 #ifdef XBRIDGE_REGS_SIM
-			printk("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).\n");
+			DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).\n");
 			if (XWIDGET_PART_NUM(0x2d000049)==XXBOW_WIDGET_PART_NUM) {
 #else
 			if (nasid_has_xbridge(nasid)) {
@@ -647,16 +608,21 @@
 			 	 */
 #ifdef SUPPORT_PRINTING_M_FORMAT
 				sprintf(pathname, EDGE_LBL_MODULE "/%M/"
+                                                EDGE_LBL_SLOT "/%s/%s",
+                                        NODEPDA(cnode)->module_id,
+                                        slotname, new_name);
 #else
-				sprintf(pathname, EDGE_LBL_MODULE "/%x/"
-#endif
+				memset(buffer, 0, 16);
+				format_module_id(buffer, NODEPDA(cnode)->module_id, MODULE_FORMAT_BRIEF);
+				sprintf(pathname, EDGE_LBL_MODULE "/%s/"
 					  	EDGE_LBL_SLOT "/%s/%s",
-					NODEPDA(cnode)->module_id,
+					buffer,
 					slotname, new_name);
+#endif
 			}
 
 			rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv);
-			printk("io_xswitch_widget_init: (2) path= %s\n", pathname);
+			DBG("io_xswitch_widget_init: (2) path= %s\n", pathname);
 		        /*
 		         * This is a weird ass code needed for error injection
 		         * purposes.
@@ -666,7 +632,7 @@
 			klhwg_baseio_inventory_add(widgetv,cnode);
 		}
 		sprintf(name, "%d", widgetnum);
-		printk("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv);
+		DBG("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv);
 		rc = hwgraph_edge_add(xswitchv, widgetv, name);
 		
 		/*
@@ -683,7 +649,7 @@
 		 */
 #ifdef XBRIDGE_REGS_SIM
 		widget_id = 0x2d000049;
-		printk("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: id hardwired to widget_id\n");
+		DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: id hardwired to widget_id\n");
 #else
 		widget_id = XWIDGET_ID_READ(nasid, widgetnum);
 #endif /* XBRIDGE_REGS_SIM */
@@ -715,21 +681,13 @@
 
 	aa = async_attach_new();
 	
-	printk("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode);
+	DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode);
 
 	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; 
 	     widgetnum++) {
-#ifdef BRINGUP
-		if (widgetnum != 0xe) 
-			io_xswitch_widget_init(xswitchv,
-				       cnodeid_to_vertex(cnode),
-				       widgetnum, aa);
-
-#else
 		io_xswitch_widget_init(xswitchv,
 				       cnodeid_to_vertex(cnode),
 				       widgetnum, aa);
-#endif /* BRINGUP */
 	}
 	/* 
 	 * Wait for parallel attach threads, if any, to complete.
@@ -798,9 +756,12 @@
 #endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */
 		}
 		if (board == NULL) {
-#ifndef CONFIG_IA64_SGI_IO
-			cmn_err(CE_WARN,
-				"Could not find PROM info for vertex %v, "
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+			PRINT_WARNING("Could not find PROM info for vertex %v, "
+				"FRU analyzer may fail",
+				vhdl);
+#else
+			PRINT_WARNING("Could not find PROM info for vertex 0x%x, "
 				"FRU analyzer may fail",
 				vhdl);
 #endif
@@ -828,16 +789,13 @@
 	hubinfo_t hubinfo;
 	int is_xswitch;
 	nodepda_t	*npdap;
-#ifndef CONFIG_IA64_SGI_IO
-	sema_t 		*peer_sema = 0;
-#else
 	struct semaphore *peer_sema = 0;
-#endif
 	uint32_t	widget_partnum;
 	nodepda_router_info_t *npda_rip;
 	cpu_cookie_t	c = 0;
+	extern int hubdev_docallouts(devfs_handle_t);
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef LATER
 	/* Try to execute on the node that we're initializing. */
 	c = setnoderun(cnodeid);
 #endif
@@ -851,13 +809,11 @@
 	 * form /hw/module/%M/slot/%d/node
 	 */
 	hubv = cnodeid_to_vertex(cnodeid);
-	printk("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap);
+	DBG("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap);
 
 	ASSERT(hubv != GRAPH_VERTEX_NONE);
 
-#if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC
 	hubdev_docallouts(hubv);
-#endif
 
 	/*
 	 * Set up the dependent routers if we have any.
@@ -877,10 +833,10 @@
 	/*
 	 * Read mfg info on this hub
 	 */
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef LATER
 	printk("io_init_node: FIXME need to implement HUB_VERTEX_MFG_INFO\n");
 	HUB_VERTEX_MFG_INFO(hubv);
-#endif /* CONFIG_IA64_SGI_IO */
+#endif /* LATER */
 
 	/* 
 	 * If nothing connected to this hub's xtalk port, we're done.
@@ -892,7 +848,7 @@
 			int index;
 
 			for (index = 0; index < 600; index++)
-				printk("Interfering with device probing!!!\n");
+				DBG("Interfering with device probing!!!\n");
 		}
 #endif
 		/* io_init_done takes cpu cookie as 2nd argument 
@@ -900,8 +856,8 @@
 		 * at the start of this thread 
 		 */
 		
-		printk("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv);
-		io_init_done(cnodeid,c);
+		DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv);
+		return;
 		/* NOTREACHED */
 	}
 
@@ -931,13 +887,13 @@
 
 	(void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv);
 
-	printk("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv);
+	DBG("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv);
 
 	ASSERT(switchv != GRAPH_VERTEX_NONE);
 
 	(void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO);
 
-	printk("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n");
+	DBG("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n");
 
 	/*
 	 * We need to find the widget id and update the basew_id field
@@ -951,7 +907,7 @@
 				widget_partnum == XBRIDGE_WIDGET_PART_NUM){
 		npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);
 
-		printk("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum);
+		DBG("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum);
 
 	} else if (widget_partnum == XBOW_WIDGET_PART_NUM ||
 				widget_partnum == XXBOW_WIDGET_PART_NUM) {
@@ -959,7 +915,7 @@
 		 * Xbow control register does not have the widget ID field.
 		 * So, hard code the widget ID to be zero.
 		 */
-		printk("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum);
+		DBG("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum);
 		npdap->basew_id = 0;
 
 #if defined(BRINGUP)
@@ -982,7 +938,7 @@
 		char widname[10];
 		sprintf(widname, "%x", npdap->basew_id);
 		(void)hwgraph_path_add(switchv, widname, &widgetv);
-		printk("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv);
+		DBG("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv);
 		ASSERT(widgetv != GRAPH_VERTEX_NONE);
 	}
 	
@@ -1043,13 +999,13 @@
 
 		/* Signal that we're done */
 		if (peer_sema) {
-			up(peer_sema);
+			mutex_unlock(peer_sema);
 		}
 		
 	}
 	else {
 	    /* Wait 'til master is done assigning widgets. */
-	    down(&npdap->xbow_sema);
+	    mutex_lock(&npdap->xbow_sema);
 	}
 
 #ifdef PROBE_TEST
@@ -1057,7 +1013,7 @@
 		int index;
 
 		for (index = 0; index < 500; index++)
-			printk("Interfering with device probing!!!\n");
+			DBG("Interfering with device probing!!!\n");
 	}
 #endif
 	/* Now both nodes can safely inititialize widgets */
@@ -1070,15 +1026,12 @@
 	 */
 	io_init_done(cnodeid,c);
 
-	printk("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid);
+	DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid);
 }
 
 
 #define IOINIT_STKSZ	(16 * 1024)
 
-#ifndef CONFIG_IA64_SGI_IO
-#include <sys/sn/iograph.h>
-#endif
 #define __DEVSTR1 	"/../.master/"
 #define __DEVSTR2 	"/target/"
 #define __DEVSTR3 	"/lun/0/disk/partition/"
@@ -1145,6 +1098,7 @@
 		{"15/" EDGE_LBL_PCI "/3/" EDGE_LBL_SCSI_CTLR "/0", 2},
 		{"14/" EDGE_LBL_PCI "/1/" EDGE_LBL_SCSI_CTLR "/0", 3},
 		{"14/" EDGE_LBL_PCI "/2/" EDGE_LBL_SCSI_CTLR "/0", 4},
+		{"15/" EDGE_LBL_PCI "/6/ohci/0/" EDGE_LBL_SCSI_CTLR "/0", 5},
 		{NULL, -1} /* must be last */
 	};
 
@@ -1181,11 +1135,7 @@
 }
 
 
-#ifndef CONFIG_IA64_SGI_IO
-#include <sys/asm/sn/ioerror_handling.h>
-#else
 #include <asm/sn/ioerror_handling.h>
-#endif
 extern devfs_handle_t 	ioc3_console_vhdl_get(void);
 devfs_handle_t		sys_critical_graph_root = GRAPH_VERTEX_NONE;
 
@@ -1203,7 +1153,7 @@
 	int			slot;
 	devfs_handle_t		baseio_console_conn;
 
-	printk("sys_critical_graph_init: FIXME.\n");
+	DBG("sys_critical_graph_init: FIXME.\n");
 	baseio_console_conn = hwgraph_connectpt_get(baseio_console_vhdl);
 
 	if (baseio_console_conn == NULL) {
@@ -1303,7 +1253,7 @@
 	devfs_handle_t		console_vhdl, pci_vhdl, enet_vhdl;
 
 
-	printk("baseio_ctlr_num_set; FIXME\n");
+	DBG("baseio_ctlr_num_set; FIXME\n");
 	console_vhdl = ioc3_console_vhdl_get();
 	if (console_vhdl == GRAPH_VERTEX_NONE)
 		return;
@@ -1384,10 +1334,8 @@
 	else {
 		rtn_val = pcibr_alloc_all_rrbs(vhdl, 0, 4,1, 4,0, 0,0, 0,0);
 	}
-#ifndef CONFIG_IA64_SGI_IO
 	if (rtn_val)
-		cmn_err(CE_WARN, "sn00_rrb_alloc: pcibr_alloc_all_rrbs failed");
-#endif
+		PRINT_WARNING("sn00_rrb_alloc: pcibr_alloc_all_rrbs failed");
 
 	if ((vendor_list[5] != PCIIO_VENDOR_ID_NONE) && 
 	    (vendor_list[7] != PCIIO_VENDOR_ID_NONE)) {
@@ -1406,10 +1354,8 @@
 		/* nothing in slot 5 or 7 */
 		rtn_val = pcibr_alloc_all_rrbs(vhdl, 1, 4,1, 4,0, 0,0, 0,0);
 	}
-#ifndef CONFIG_IA64_SGI_IO
 	if (rtn_val)
-		cmn_err(CE_WARN, "sn00_rrb_alloc: pcibr_alloc_all_rrbs failed");
-#endif
+		PRINT_WARNING("sn00_rrb_alloc: pcibr_alloc_all_rrbs failed");
 }
 
 
@@ -1423,17 +1369,18 @@
 	/* Governor on init threads..bump up when safe 
 	 * (beware many devfs races) 
 	 */
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef LATER
 	int io_init_node_threads = 2;	
 #endif
 	cnodeid_t cnodeid, active;
 
-	init_MUTEX(&io_init_sema);
-
+#ifdef LINUX_KERNEL_THREADS
+	sema_init(&io_init_sema, 0);
+#endif
 
 	active = 0;
 	for (cnodeid = 0; cnodeid < maxnodes; cnodeid++) {
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef LINUX_KERNEL_THREADS
 		char thread_name[16];
 		extern int io_init_pri;
 
@@ -1448,20 +1395,17 @@
 			io_init_pri, KT_PS, (st_func_t *)io_init_node,
 			(void *)(long)cnodeid, 0, 0, 0);
 #else
-                printk("init_all_devices: Calling io_init_node() for cnode %d\n", cnodeid);
+                DBG("init_all_devices: Calling io_init_node() for cnode %d\n", cnodeid);
                 io_init_node(cnodeid);
 
-		printk("init_all_devices: Done io_init_node() for cnode %d\n", cnodeid);
-
-#endif /* !CONFIG_IA64_SGI_IO */
+		DBG("init_all_devices: Done io_init_node() for cnode %d\n", cnodeid);
 
+#endif /* LINUX_KERNEL_THREADS */
 
+#ifdef LINUX_KERNEL_THREADS
 		/* Limit how many nodes go at once, to not overload hwgraph */
 		/* TBD: Should timeout */
-#ifdef AA_DEBUG
-		printk("started thread for cnode %d\n", cnodeid);
-#endif
-#ifdef LINUX_KERNEL_THREADS
+		DBG("started thread for cnode %d\n", cnodeid);
 		active++;
 		if (io_init_node_threads && 
 			active >= io_init_node_threads) {
@@ -1476,9 +1420,9 @@
 
 	while (active > 0) {
 #ifdef AA_DEBUG
-	    printk("waiting, %d still active\n", active);
+	    DBG("waiting, %d still active\n", active);
 #endif
-	    sema(&io_init_sema);
+	    down(&io_init_sema);
 	    active--;
 	}
 
@@ -1534,22 +1478,22 @@
 		int i;
 		int viable_found = 0;
 
-		printk("Only controller numbers 0..%d  are supported for\n", NUM_BASE_IO_SCSI_CTLR-1);
-		printk("prom \"root\" variables of the form dksXdXsX.\n");
-		printk("To use another disk you must use the full hardware graph path\n\n");
-		printk("Possible controller numbers for use in 'dksXdXsX' on this system: ");
+		DBG("Only controller numbers 0..%d  are supported for\n", NUM_BASE_IO_SCSI_CTLR-1);
+		DBG("prom \"root\" variables of the form dksXdXsX.\n");
+		DBG("To use another disk you must use the full hardware graph path\n\n");
+		DBG("Possible controller numbers for use in 'dksXdXsX' on this system: ");
 		for (i=0; i<NUM_BASE_IO_SCSI_CTLR; i++) {
 			if (base_io_scsi_ctlr_vhdl[i] != GRAPH_VERTEX_NONE) {
-				printk("%d ", i);
+				DBG("%d ", i);
 				viable_found=1;
 			}
 		}
 		if (viable_found)
-			printk("\n");
+			DBG("\n");
 		else
-			printk("none found!\n");
+			DBG("none found!\n");
 
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef LATER
 		if (kdebug)
 			debug("ring");
 #endif
@@ -1579,4 +1523,132 @@
 	*tmp2++ = '/';
 	strcpy(tmp2, EDGE_LBL_BLOCK);
 	strcpy(devnm,tmpnm);
+}
+
+static
+struct io_brick_map_s io_brick_tab[] = {
+
+/* Ibrick widget number to PCI bus number map */
+  {
+        'I',                                    /* Ibrick type    */ 
+    /*  PCI Bus #                                  Widget #       */
+     {  0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        0,                                      /* 0x8            */
+        0,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        0,                                      /* 0xc            */
+        0,                                      /* 0xd            */
+        2,                                      /* 0xe            */
+        1                                       /* 0xf            */
+     }
+  },
+
+/* Pbrick widget number to PCI bus number map */
+  {
+        'P',                                    /* Pbrick type    */ 
+    /*  PCI Bus #                                  Widget #       */
+     {  0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        2,                                      /* 0x8            */
+        1,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        5,                                      /* 0xc            */
+        6,                                      /* 0xd            */
+        4,                                      /* 0xe            */
+        3                                       /* 0xf            */
+     }
+  },
+
+/* Xbrick widget to XIO slot map */
+  {
+        'X',                                    /* Xbrick type    */ 
+    /*  XIO Slot #                                 Widget #       */
+     {  0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        1,                                      /* 0x8            */
+        2,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        3,                                      /* 0xc            */
+        4,                                      /* 0xd            */
+        0,                                      /* 0xe            */
+        0                                       /* 0xf            */
+     }
+  }
+};
+
+/*
+ * Use the brick's type to map a widget number to a meaningful int
+ */
+int
+io_brick_map_widget(char brick_type, int widget_num)
+{
+        int num_bricks, i;
+
+        /* Calculate number of bricks in table */
+        num_bricks = sizeof(io_brick_tab)/sizeof(io_brick_tab[0]);
+
+        /* Look for brick prefix in table */
+        for (i = 0; i < num_bricks; i++) {
+               if (brick_type == io_brick_tab[i].ibm_type)
+                       return(io_brick_tab[i].ibm_map_wid[widget_num]);
+        }
+
+        return 0;
+
+}
+
+/*
+ * Use the device's vertex to map the device's widget to a meaningful int
+ */
+int
+io_path_map_widget(devfs_handle_t vertex)
+{
+        char hw_path_name[MAXDEVNAME];
+        char *wp, *bp, *sp = NULL;
+        int  widget_num;
+	long atoi(char *);
+	int hwgraph_vertex_name_get(devfs_handle_t vhdl, char *buf, uint buflen);
+
+
+        /* Get the full path name of the vertex */
+        if (GRAPH_SUCCESS != hwgraph_vertex_name_get(vertex, hw_path_name,
+                                                     MAXDEVNAME))
+                return 0;
+
+        /* Find the widget number in the path name */
+        wp = strstr(hw_path_name, "/"EDGE_LBL_XTALK"/");
+        if (wp == NULL)
+                return 0;
+        widget_num = atoi(wp+7);
+        if (widget_num < XBOW_PORT_8 || widget_num > XBOW_PORT_F)
+                return 0;
+
+        /* Find "brick" in the path name */
+        bp = strstr(hw_path_name, "brick");
+        if (bp == NULL)
+                return 0;
+
+        /* Find preceding slash */
+        sp = bp;
+        while (sp > hw_path_name) {
+                sp--;
+                if (*sp == '/')
+                        break;
+        }
+
+        /* Invalid if no preceding slash */
+        if (!sp)
+                return 0;
+
+        /* Bump slash pointer to "brick" prefix */
+        sp++;
+        /*
+         * Verify "brick" prefix length;  valid exaples:
+         * 'I' from "/Ibrick"
+         * 'P' from "/Pbrick"
+         * 'X' from "/Xbrick"
+         */
+         if ((bp - sp) != 1)
+                return 0;
+
+        return (io_brick_map_widget(*sp, widget_num));
+
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/module.c linux/arch/ia64/sn/io/module.c
--- v2.4.3/linux/arch/ia64/sn/io/module.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/module.c	Thu Apr 12 12:16:35 2001
@@ -9,13 +9,11 @@
  */
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/invent.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
-#include <asm/sn/cmn_err.h>
 #include <asm/sn/xtalk/xbow.h>
 #include <asm/sn/pci/bridge.h>
 #include <asm/sn/klconfig.h>
@@ -24,12 +22,17 @@
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/xtalk/xswitch.h>
 #include <asm/sn/nodepda.h>
+#include <asm/sn/sn_cpuid.h>
 
 
-#define LDEBUG	1	
+/* #define LDEBUG	1	*/
 
-#define DPRINTF		if (LDEBUG) printk
+#ifdef LDEBUG
+#define DPRINTF		printk
 #define printf		printk
+#else
+#define DPRINTF(x...)
+#endif
 
 module_t	       *modules[MODULE_MAX];
 int			nummodules;
@@ -100,8 +103,6 @@
 {
     int			i;
 
-    DPRINTF("module_lookup: id=%d\n", id);
-
     for (i = 0; i < nummodules; i++)
 	if (modules[i]->id == id) {
 	    DPRINTF("module_lookup: found m=0x%p\n", modules[i]);
@@ -125,29 +126,29 @@
 {
     module_t	       *m;
     int			i;
+    char		buffer[16];
 
-    DPRINTF("module_add_node: id=%x node=%d\n", id, n);
+#ifdef __ia64
+    memset(buffer, 0, 16);
+    format_module_id(buffer, id, MODULE_FORMAT_BRIEF);
+    DPRINTF("module_add_node: id=%s node=%d\n", buffer, n);
+#endif
 
     if ((m = module_lookup(id)) == 0) {
-#ifndef CONFIG_IA64_SGI_IO
+#ifdef LATER
 	m = kmem_zalloc_node(sizeof (module_t), KM_NOSLEEP, n);
 #else
 	m = kmalloc(sizeof (module_t), GFP_KERNEL);
 	memset(m, 0 , sizeof(module_t));
-	printk("Module nodecnt = %d\n", m->nodecnt); 
 #endif
 	ASSERT_ALWAYS(m);
 
-	DPRINTF("module_add_node: m=0x%p\n", m);
-
 	m->id = id;
 	spin_lock_init(&m->lock);
 
-	init_MUTEX_LOCKED(&m->thdcnt);
+	mutex_init_locked(&m->thdcnt);
 
-printk("Set elsc to 0x%p on node %d\n", &m->elsc, get_nasid());
-
-set_elsc(&m->elsc);
+// set_elsc(&m->elsc);
 	elsc_init(&m->elsc, COMPACT_TO_NASID_NODEID(n));
 	spin_lock_init(&m->elsclock);
 
@@ -162,8 +163,7 @@
 
     m->nodes[m->nodecnt++] = n;
 
-printk("module_add_node: module %x now has %d nodes\n", id, m->nodecnt);
-    DPRINTF("module_add_node: module %x now has %d nodes\n", id, m->nodecnt);
+    DPRINTF("module_add_node: module %s now has %d nodes\n", buffer, m->nodecnt);
 
     return m;
 }
@@ -172,6 +172,7 @@
 {
     lboard_t	       *board;
     klmod_serial_num_t *comp;
+    char * bcopy(const char * src, char * dest, int count);
 
     board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid),
 			KLTYPE_MIDPLANE8);
@@ -204,14 +205,8 @@
     if (m->snum_valid)
 	return 1;
     else {
-#ifndef CONFIG_IA64_SGI_IO
-	cmn_err(CE_WARN | CE_MAINTENANCE,
-		"Invalid serial number for module %d, "
-		"possible missing or invalid NIC.", m->id);
-#else
-	printk("Invalid serial number for module %d, "
+	DPRINTF("Invalid serial number for module %d, "
 		"possible missing or invalid NIC.", m->id);
-#endif
 	return 0;
     }
 }
@@ -246,32 +241,12 @@
 	    nserial);
 
     if (nserial == 0)
-	cmn_err(CE_WARN, "No serial number found.");
+	PRINT_WARNING("io_module_init: No serial number found.\n");
 }
 
-#ifdef BRINGUP
-elsc_t *Elsc[100];
-
-void
-set_elsc(elsc_t *p)
-{
-      Elsc[get_nasid()] = p;
-}
-#endif
-
 elsc_t *get_elsc(void)
 {
-#ifdef BRINGUP
-return(Elsc[get_nasid()]);
-#else
-	if ( NODEPDA(get_nasid())->module == (module_t *)0 ) {
-		printf("get_elsc() for nasd %d fails\n", get_nasid());
-//		return((elsc_t *)0);
-	}
-	return &NODEPDA(get_nasid())->module->elsc;
-
-//	return &NODEPDA(NASID_TO_COMPACT_NODEID(0))->module->elsc;
-#endif
+	return &NODEPDA(cpuid_to_cnodeid(smp_processor_id()))->module->elsc;
 }
 
 int
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/pci.c linux/arch/ia64/sn/io/pci.c
--- v2.4.3/linux/arch/ia64/sn/io/pci.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/pci.c	Thu Apr  5 12:51:47 2001
@@ -14,7 +14,6 @@
 #include <linux/pci.h>
 #include <asm/sn/types.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/cmn_err.h>
 #include <asm/sn/iobus.h>
 #include <asm/sn/iograph.h>
 #include <asm/param.h>
@@ -250,18 +249,9 @@
 pci_fixup_ioc3(struct pci_dev *d)
 {
         int 		i;
-	int 		slot;
-	unsigned long 	res = 0;
-	unsigned int 	val, size;
-	int 		ret;
-	u_short 	command;
+	unsigned int 	size;
 
-	devfs_handle_t 	device_vertex;
 	devfs_handle_t	bridge_vhdl = pci_bus_to_vertex(d->bus->number);
-	pcibr_soft_t 	pcibr_soft = (pcibr_soft_t) hwgraph_fastinfo_get(bridge_vhdl);
-	devfs_handle_t  xconn_vhdl = pcibr_soft->bs_conn;
-	bridge_t 	*bridge = pcibr_soft->bs_base;
-	bridgereg_t 	devreg;
 
         /* IOC3 only decodes 0x20 bytes of the config space, reading
 	 * beyond that is relatively benign but writing beyond that
@@ -271,7 +261,7 @@
 	 *       currently we hack this with special code in 
 	 *	 sgi_pci_intr_support()
 	 */
-        printk("pci_fixup_ioc3: Fixing base addresses for ioc3 device %s\n", d->slot_name);
+        DBG("pci_fixup_ioc3: Fixing base addresses for ioc3 device %s\n", d->slot_name);
 
 	/* I happen to know from the spec that the ioc3 needs only 0xfffff 
 	 * The standard pci trick of writing ~0 to the baddr and seeing
@@ -296,7 +286,9 @@
 	 * DEV_DIRECT bit.  This will not work if IOC3 is not on Slot 
 	 * 4.
 	 */
-	*(volatile u32 *)0xc0000a000f000220 |= 0x90000;
+	DBG("pci_fixup_ioc3: FIXME .. need to take NASID into account when setting IOC3 devreg 0x%x\n", *(volatile u32 *)0xc0000a000f000220);
+
+ 	*(volatile u32 *)0xc0000a000f000220 |= 0x90000; 
 
         d->subsystem_vendor = 0;
         d->subsystem_device = 0;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/pci_bus_cvlink.c linux/arch/ia64/sn/io/pci_bus_cvlink.c
--- v2.4.3/linux/arch/ia64/sn/io/pci_bus_cvlink.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/pci_bus_cvlink.c	Thu Apr 12 12:16:35 2001
@@ -16,7 +16,6 @@
 #include <asm/sn/types.h>
 #include <asm/sn/hack.h>
 #include <asm/sn/sgi.h>
-#include <asm/sn/cmn_err.h>
 #include <asm/sn/iobus.h>
 #include <asm/sn/iograph.h>
 #include <asm/param.h>
@@ -32,23 +31,32 @@
 #include <asm/sn/xtalk/xtalkaddrs.h>
 #include <asm/sn/klconfig.h>
 #include <asm/sn/io.h>
-#include <asm/sn/pci/pci_bus_cvlink.h>
 
 #include <asm/sn/pci/pciio.h>
 // #include <sys/ql.h>
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/pci/pcibr_private.h>
 extern int bridge_rev_b_data_check_disable;
+#include <asm/sn/pci/pci_bus_cvlink.h>
 
 #define MAX_PCI_XWIDGET 256
-devfs_handle_t busnum_to_xwidget[MAX_PCI_XWIDGET];
+devfs_handle_t busnum_to_pcibr_vhdl[MAX_PCI_XWIDGET];
 nasid_t busnum_to_nid[MAX_PCI_XWIDGET];
+void * busnum_to_atedmamaps[MAX_PCI_XWIDGET];
 unsigned char num_bridges;
 static int done_probing = 0;
 
 static int pci_bus_map_create(devfs_handle_t xtalk);
 devfs_handle_t devfn_to_vertex(unsigned char busnum, unsigned int devfn);
 
+#define SN1_IOPORTS_UNIT 256
+#define MAX_IOPORTS 0xffff
+#define MAX_IOPORTS_CHUNKS (MAX_IOPORTS / SN1_IOPORTS_UNIT)
+struct ioports_to_tlbs_s ioports_to_tlbs[MAX_IOPORTS_CHUNKS];
+unsigned long sn1_allocate_ioports(unsigned long pci_address);
+
+
+
 /*
  * pci_bus_cvlink_init() - To be called once during initialization before 
  *	SGI IO Infrastructure init is called.
@@ -56,9 +64,13 @@
 void
 pci_bus_cvlink_init(void)
 {
-
-	memset(busnum_to_xwidget, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET);
+	memset(busnum_to_pcibr_vhdl, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET);
 	memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET);
+
+	memset(busnum_to_atedmamaps, 0x0, sizeof(void *) * MAX_PCI_XWIDGET);
+
+	memset(ioports_to_tlbs, 0x0, sizeof(ioports_to_tlbs));
+
 	num_bridges = 0;
 }
 
@@ -70,27 +82,13 @@
 pci_bus_to_vertex(unsigned char busnum)
 {
 
-	devfs_handle_t	xwidget;
 	devfs_handle_t	pci_bus = NULL;
 
 
 	/*
 	 * First get the xwidget vertex.
 	 */
-	xwidget = busnum_to_xwidget[busnum];
-	if (!xwidget)
-		return (NULL);
-
-	/*
-	 * Use devfs to get the pci vertex from xwidget.
-	 */
-	if (hwgraph_traverse(xwidget, EDGE_LBL_PCI, &pci_bus) != GRAPH_SUCCESS) {
-		if (!pci_bus) {
-			printk("pci_bus_to_vertex: Cannot find pci bus for given bus number %d\n", busnum);
-			return (NULL);
-		}
-	}
-
+	pci_bus = busnum_to_pcibr_vhdl[busnum];
 	return(pci_bus);
 }
 
@@ -138,7 +136,6 @@
 
 	if (hwgraph_traverse(pci_bus, name, &device_vertex) != GRAPH_SUCCESS) {
 		if (!device_vertex) {
-			printk("devfn_to_vertex: Unable to get slot&func %s from pci vertex 0x%p\n", name, pci_bus);
 			return(NULL);
 		}
 	}
@@ -175,6 +172,61 @@
 }
 
 /*
+ * sn1_allocate_ioports() - This routine provides the allocation and 
+ *	mappings between Linux style IOPORTs management.
+ *
+ *	For simplicity sake, SN1 will allocate IOPORTs in chunks of 
+ *	256bytes .. irrespective of what the card desires.  This may 
+ *	have to change when we understand how to deal with legacy ioports 
+ *	which are hardcoded in some drivers e.g. SVGA.
+ *
+ *	Ofcourse, the SN1 IO Infrastructure has no concept of IOPORT numbers.
+ *	It will remain so.  The IO Infrastructure will continue to map 
+ *	IO Resource just like IRIX.  When this is done, we map IOPORT 
+ *	chunks to these resources.  The Linux drivers will see and use real 
+ *	IOPORT numbers.  The various IOPORT access macros e.g. inb/outb etc. 
+ *	does the munging of these IOPORT numbers to make a Uncache Virtual 
+ *	Address.  This address via the tlb entries generates the PCI Address 
+ *	allocated by the SN1 IO Infrastructure Layer.
+ */
+static unsigned long sn1_ioport_num = 0x100; /* Reserve room for Legacy stuff */
+unsigned long
+sn1_allocate_ioports(unsigned long pci_address)
+{
+	
+	unsigned long ioport_index;
+
+	/*
+	 * Just some idiot checking ..
+	 */
+	if ( sn1_ioport_num > 0xffff ) {
+		printk("sn1_allocate_ioports: No more IO PORTS available\n");
+		return(-1);
+	}
+
+	/*
+	 * See Section 4.1.1.5 of Intel IA-64 Acrchitecture Software Developer's
+	 * Manual for details.
+	 */
+	ioport_index = sn1_ioport_num / SN1_IOPORTS_UNIT;
+	ioports_to_tlbs[ioport_index].ppn = pci_address;
+	ioports_to_tlbs[ioport_index].p = 1; /* Present Bit */
+	ioports_to_tlbs[ioport_index].ma = 5; /* Memory Attributes */
+	ioports_to_tlbs[ioport_index].a = 0; /* Set Data Access Bit Fault */
+	ioports_to_tlbs[ioport_index].d = 0; /* Dirty Bit */
+	ioports_to_tlbs[ioport_index].pl = 3;/* Privilege Level - All levels can R/W*/
+	ioports_to_tlbs[ioport_index].ar = 2; /* Access Rights - R/W only*/
+	ioports_to_tlbs[ioport_index].ed = 0; /* Exception Deferral Bit */
+	ioports_to_tlbs[ioport_index].ig = 0; /* Ignored */
+
+	printk("sn1_allocate_ioports: ioport_index 0x%x ioports_to_tlbs 0x%p\n", ioport_index, ioports_to_tlbs[ioport_index].ppn);
+	
+	sn1_ioport_num += SN1_IOPORTS_UNIT;
+
+	return(sn1_ioport_num - SN1_IOPORTS_UNIT);
+}
+
+/*
  * sn1_pci_fixup() - This routine is called when platform_pci_fixup() is 
  *	invoked at the end of pcibios_init() to link the Linux pci 
  *	infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c
@@ -189,6 +241,11 @@
 	struct pci_dev *device_dev = NULL;
 	struct sn1_widget_sysdata *widget_sysdata;
 	struct sn1_device_sysdata *device_sysdata;
+	unsigned long ioport;
+	pciio_intr_t intr_handle;
+	int cpuid, bit;
+	devfs_handle_t *device_vertex;
+	pciio_intr_line_t lines;
 	extern void sn1_pci_find_bios(void);
 
 
@@ -204,7 +261,6 @@
         devfs_handle_t  bridge_vhdl = pci_bus_to_vertex(0);
         pcibr_soft_t    pcibr_soft = (pcibr_soft_t) hwgraph_fastinfo_get(bridge_vhdl);
 	bridge_t        *bridge = pcibr_soft->bs_base;
-printk("Before Changing PIO Map Address:\n");
         printk("pci_fixup_ioc3: Before devreg fixup\n");
         printk("pci_fixup_ioc3: Devreg 0 0x%x\n", bridge->b_device[0].reg);
         printk("pci_fixup_ioc3: Devreg 1 0x%x\n", bridge->b_device[1].reg);
@@ -280,16 +336,11 @@
 			size = device_dev->resource[idx].end -
 				device_dev->resource[idx].start;
 			if (size) {
-res = 0;
-res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4);
-printk("Before pciio_pio_addr Base address %d = 0x%lx\n", idx, res);
-
-				printk(" Changing device %d:%d resource start address from 0x%lx", 
-				PCI_SLOT(device_dev->devfn),PCI_FUNC(device_dev->devfn),
-				device_dev->resource[idx].start);
-				device_dev->resource[idx].start = 
-				(unsigned long)pciio_pio_addr(vhdl, 0, 
-					PCIIO_SPACE_WIN(idx), 0, size, 0, PCIIO_BYTE_STREAM);
+				res = 0;
+				res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4);
+				device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, PCIIO_BYTE_STREAM);
+
+/* printk("sn1_pci_fixup: Mapped Address = 0x%p size = 0x%x\n", device_dev->resource[idx].start, size); */
 			}
 			else
 				continue;
@@ -304,13 +355,14 @@
 				device_dev->resource[idx].start & 0xfffff7ffffffffff;
 			device_dev->resource[idx].end = 
 				device_dev->resource[idx].end & 0xfffff7ffffffffff;
-			printk(" to 0x%lx\n", device_dev->resource[idx].start);
-res = 0;
-res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4);
-printk("After pciio_pio_addr Base address %d = 0x%lx\n", idx, res);
-
-			if (device_dev->resource[idx].flags & IORESOURCE_IO)
+			res = 0;
+			res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4);
+			if (device_dev->resource[idx].flags & IORESOURCE_IO) {
 				cmd |= PCI_COMMAND_IO;
+				ioport = sn1_allocate_ioports(device_dev->resource[idx].start);
+				/* device_dev->resource[idx].start = ioport; */
+				/* device_dev->resource[idx].end = ioport + SN1_IOPORTS_UNIT */
+			}
 			else if (device_dev->resource[idx].flags & IORESOURCE_MEM)
 				cmd |= PCI_COMMAND_MEMORY;
 		}
@@ -319,9 +371,6 @@
 		 */
 		size = device_dev->resource[PCI_ROM_RESOURCE].end -
 			device_dev->resource[PCI_ROM_RESOURCE].start;
-		printk(" Changing device %d:%d ROM resource start address from 0x%lx", 
-			PCI_SLOT(device_dev->devfn),PCI_FUNC(device_dev->devfn),
-			device_dev->resource[PCI_ROM_RESOURCE].start);
 		device_dev->resource[PCI_ROM_RESOURCE].start =
 			(unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0, 
 				size, 0, PCIIO_BYTE_STREAM);
@@ -341,24 +390,26 @@
 					   /* bit gets dropped .. no harm */
 		pci_write_config_word(device_dev, PCI_COMMAND, cmd);
 
-		printk("  to 0x%lx\n", device_dev->resource[PCI_ROM_RESOURCE].start);
+		pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, &lines);
+#ifdef BRINGUP
+		if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
+			device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) {
+				lines = 1;
+		}
 
-		/*
-		 * Set the irq correctly.
-		 * Bits 7:3 = slot
-		 * Bits 2:0 = function
-		 *
-		 * In the IRQ we will have:
-		 *	Bits 24:16 = bus number
-		 *	Bits 15:8 = slot|func number
-		 */
-		irq = 0;
-		irq = (irq | (device_dev->devfn << 8));
-		irq = (irq | ( (device_dev->bus->number & 0xff) << 16) );
+#endif
+ 
+		device_sysdata = (struct sn1_device_sysdata *)device_dev->sysdata;
+		device_vertex = device_sysdata->vhdl;
+ 
+		intr_handle = pciio_intr_alloc(device_vertex, NULL, lines, device_vertex);
+
+		bit = intr_handle->pi_irq;
+		cpuid = intr_handle->pi_cpu;
+		irq = bit_pos_to_irq(bit);
+		irq = irq + (cpuid << 8);
+		pciio_intr_connect(intr_handle, NULL, NULL, NULL);
 		device_dev->irq = irq;
-printk("sn1_pci_fixup: slot= %d  fn= %d  vendor= 0x%x  device= 0x%x  irq= 0x%x\n",
-PCI_SLOT(device_dev->devfn),PCI_FUNC(device_dev->devfn),device_dev->vendor,
-device_dev->device, device_dev->irq);
 
 	}
 #endif	/* REAL_HARDWARE */
@@ -369,7 +420,6 @@
         pcibr_soft_t    pcibr_soft = (pcibr_soft_t) hwgraph_fastinfo_get(bridge_vhdl);
         bridge_t        *bridge = pcibr_soft->bs_base;
 
-printk("After Changing PIO Map Address:\n");
         printk("pci_fixup_ioc3: Before devreg fixup\n");
         printk("pci_fixup_ioc3: Devreg 0 0x%x\n", bridge->b_device[0].reg);
         printk("pci_fixup_ioc3: Devreg 1 0x%x\n", bridge->b_device[1].reg);
@@ -386,6 +436,25 @@
 
 /*
  * pci_bus_map_create() - Called by pci_bus_to_hcl_cvlink() to finish the job.
+ *
+ *	Linux PCI Bus numbers are assigned from lowest module_id numbers
+ *	(rack/slot etc.) starting from HUB_WIDGET_ID_MAX down to 
+ *	HUB_WIDGET_ID_MIN:
+ *		widgetnum 15 gets lower Bus Number than widgetnum 14 etc.
+ *
+ *	Given 2 modules 001c01 and 001c02 we get the following mappings:
+ *		001c01, widgetnum 15 = Bus number 0
+ *		001c01, widgetnum 14 = Bus number 1
+ *		001c02, widgetnum 15 = Bus number 3
+ *		001c02, widgetnum 14 = Bus number 4
+ *		etc.
+ *
+ * The rational for starting Bus Number 0 with Widget number 15 is because 
+ * the system boot disks are always connected via Widget 15 Slot 0 of the 
+ * I-brick.  Linux creates /dev/sd* devices(naming) strating from Bus Number 0 
+ * Therefore, /dev/sda1 will be the first disk, on Widget 15 of the lowest 
+ * module id(Master Cnode) of the system.
+ *	
  */
 static int 
 pci_bus_map_create(devfs_handle_t xtalk)
@@ -402,10 +471,21 @@
 	/*
 	 * Loop throught this vertex and get the Xwidgets ..
 	 */
-	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+	for (widgetnum = HUB_WIDGET_ID_MAX; widgetnum >= HUB_WIDGET_ID_MIN; widgetnum--) {
+        {
+                int pos;
+                char dname[256];
+                pos = devfs_generate_path(xtalk, dname, 256);
+                printk("%s : path= %s\n", __FUNCTION__, &dname[pos]);
+        }
+
 		sprintf(pathname, "%d", widgetnum);
 		xwidget = NULL;
 		
+		/*
+		 * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget
+		 *	     /hw/module/001c16/Pbrick/xtalk/8/pci/1 is device
+		 */
 		rv = hwgraph_traverse(xtalk, pathname, &xwidget);
 		if ( (rv != GRAPH_SUCCESS) ) {
 			if (!xwidget)
@@ -425,25 +505,35 @@
 		 * Should not be any race here ...
 		 */
 		num_bridges++;
-		busnum_to_xwidget[num_bridges - 1] = xwidget;
+		busnum_to_pcibr_vhdl[num_bridges - 1] = pci_bus;
 
 		/*
 		 * Get the master node and from there get the NASID.
 		 */
 		master_node_vertex = device_master_get(xwidget);
 		if (!master_node_vertex) {
-			printk(" **** pci_bus_map_create: Unable to get .master for vertex 0x%p **** \n", xwidget);
+			printk("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", xwidget);
 		}
 	
 		hubinfo_get(master_node_vertex, &hubinfo);
 		if (!hubinfo) {
-			printk(" **** pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p ****\n", master_node_vertex);
+			printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", master_node_vertex);
 			return(1);
 		} else {
 			busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid;
 		}
 
-		printk("pci_bus_map_create: Found Hub nasid %d PCI Xwidget 0x%p  widgetnum= %d\n", hubinfo->h_nasid, xwidget, widgetnum);
+		/*
+		 * Pre assign DMA maps needed for 32 Bits Page Map DMA.
+		 */
+		busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc(
+			sizeof(struct sn1_dma_maps_s) * 512, GFP_KERNEL);
+		if (!busnum_to_atedmamaps[num_bridges - 1])
+			printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, xwidget);
+
+		memset(busnum_to_atedmamaps[num_bridges - 1], 0x0, 
+			sizeof(struct sn1_dma_maps_s) * 512);
+
 	}
 
         return(0);
@@ -468,6 +558,9 @@
 	graph_vertex_place_t placeptr = EDGE_PLACE_WANT_REAL_EDGES;
 	int rv = 0;
 	char name[256];
+	int master_iobrick;
+	moduleid_t iobrick_id;
+	int i;
 
 	/*
 	 * Iterate throught each xtalk links in the system ..
@@ -480,42 +573,48 @@
 	devfs_hdl = hwgraph_path_to_vertex("/dev/hw/module");
 
 	/*
-	 * Loop throught this directory "/devfs/hw/module/" and get each 
-	 * of it's entry.
-	 */
-	while (1) {
-	
-		/* Get vertex of component /dev/hw/<module_number> */
-		memset((char *)name, '0', 256);
-		module_comp = NULL;
-		rv = hwgraph_edge_get_next(devfs_hdl, (char *)name, &module_comp, (uint *)&placeptr);
-		if ((rv == 0) && (module_comp)) {
-			/* Found a valid entry */
-			node = NULL;
-			rv = hwgraph_edge_get(module_comp, "node", &node);
-
-		} else {
-			printk("pci_bus_to_hcl_cvlink: No more Module Component.\n");
-			return(0);
+	 * To provide consistent(not persistent) device naming, we need to start 
+	 * bus number allocation from the C-Brick with the lowest module id e.g. 001c01 
+	 * with an attached I-Brick.  Find the master_iobrick.
+	 */
+	master_iobrick = -1;
+	for (i = 0; i < nummodules; i++) {
+		moduleid_t iobrick_id; 
+		iobrick_id = iobrick_module_get(&modules[i]->elsc);
+		if (iobrick_id > 0) { /* Valid module id */
+			if (MODULE_GET_BTYPE(iobrick_id) == MODULE_IBRICK) {
+				master_iobrick = i;
+				break;
+			}
 		}
+	}
 
-		if ( (rv != 0) || (!node) ){
-			printk("pci_bus_to_hcl_cvlink: Module Component does not have node vertex.\n");
-			continue;
-		} else {
-			xtalk = NULL;
-			rv = hwgraph_edge_get(node, "xtalk", &xtalk);
-			if ( (rv != 0) || (xtalk == NULL) ){
-				printk("pci_bus_to_hcl_cvlink: Node has no xtalk vertex.\n");
-				continue;
-			}
+	/*
+	 * The master_iobrick gets bus 0 and 1.
+	 */
+	if (master_iobrick >= 0) {
+		memset(name, 0, 256);
+		format_module_id(name, modules[master_iobrick]->id, MODULE_FORMAT_BRIEF);
+		strcat(name, "/node/xtalk");
+		xtalk = NULL;
+		rv = hwgraph_edge_get(devfs_hdl, name, &xtalk);
+		pci_bus_map_create(xtalk);
+	}
+		
+	/*
+	 * Now go do the rest of the modules, starting from the C-Brick with the lowest 
+	 * module id, remembering to skip the master_iobrick, which was done above.
+	 */
+	for (i = 0; i < nummodules; i++) {
+		if (i == master_iobrick) {
+			continue; /* Did the master_iobrick already. */
 		}
 
-		printk("pci_bus_to_hcl_cvlink: Found Module %s node vertex = 0x%p xtalk vertex = 0x%p\n", name, node, xtalk);
-		/*
-		 * Call routine to get the existing PCI Xwidget and create
-		 * the convenience link from "/devfs/hw/pci_bus/.."
-		 */
+		memset(name, 0, 256);
+		format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF);
+		strcat(name, "/node/xtalk");
+		xtalk = NULL;
+		rv = hwgraph_edge_get(devfs_hdl, name, &xtalk);
 		pci_bus_map_create(xtalk);
 	}
 
@@ -539,10 +638,8 @@
 	struct sn1_widget_sysdata *widget_sysdata;
 	struct sn1_device_sysdata *device_sysdata;
 
-	printk("sgi_pci_intr_support: Called with requested_irq 0x%x\n", requested_irq);
-
 	if (!dev_desc || !bus_vertex || !device_vertex) {
-		printk("sgi_pci_intr_support: Invalid parameter dev_desc 0x%p, bus_vertex 0x%p, device_vertex 0x%p\n", dev_desc, bus_vertex, device_vertex);
+		printk("WARNING: sgi_pci_intr_support: Invalid parameter dev_desc 0x%p, bus_vertex 0x%p, device_vertex 0x%p\n", dev_desc, bus_vertex, device_vertex);
 		return(-1);
 	}
 
@@ -577,15 +674,11 @@
 	if (pci_dev->vendor == PCI_VENDOR_ID_SGI &&
 	    pci_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) {
 		*lines = 1;
-		printk("%s : IOC3 HACK: lines= %d\n", __FUNCTION__, *lines);
 	}
 #endif /* BRINGUP */
 
 	/* Not supported currently */
 	*dev_desc = NULL;
-
-	printk("sgi_pci_intr_support: Device Descriptor 0x%p, Bus Vertex 0x%p, Interrupt Pins 0x%x, Device Vertex 0x%p\n", *dev_desc, *bus_vertex, *lines, *device_vertex);
-
 	return(0);
 
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/pci_dma.c linux/arch/ia64/sn/io/pci_dma.c
--- v2.4.3/linux/arch/ia64/sn/io/pci_dma.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/pci_dma.c	Thu Apr 12 12:16:35 2001
@@ -21,9 +21,6 @@
 #ifndef _LANGUAGE_C
 #define _LANGUAGE_C 99
 #endif
-#ifndef CONFIG_IA64_SGI_IO
-#define CONFIG_IA64_SGI_IO 99
-#endif
 
 #include <asm/io.h>
 #include <asm/sn/sgi.h>
@@ -32,9 +29,9 @@
 #include <asm/sn/pci/pcibr.h>
 #include <asm/sn/pci/pcibr_private.h>
 #include <asm/sn/iobus.h>
-#include <asm/sn/pci/pci_bus_cvlink.h>
 #include <asm/sn/types.h>
 #include <asm/sn/alenlist.h>
+#include <asm/sn/pci/pci_bus_cvlink.h>
 
 /*
  * this is REALLY ugly, blame it on gcc's lame inlining that we
@@ -43,13 +40,69 @@
 #if LANGUAGE_C == 99
 #undef LANGUAGE_C
 #endif
-#if _LANGUAGE_C == 99
-#undef _LANGUAGE_C
-#endif
 #if CONFIG_IA64_SGI_IO == 99
 #undef CONFIG_IA64_SGI_IO
 #endif
 
+pciio_dmamap_t get_free_pciio_dmamap(devfs_handle_t);
+struct sn1_dma_maps_s *find_sn1_dma_map(dma_addr_t, unsigned char);
+extern devfs_handle_t busnum_to_pcibr_vhdl[];
+extern nasid_t busnum_to_nid[];
+extern void * busnum_to_atedmamaps[];
+
+/*
+ * Get a free pciio_dmamap_t entry.
+ */
+pciio_dmamap_t
+get_free_pciio_dmamap(devfs_handle_t pci_bus)
+{
+	int i;
+	struct sn1_dma_maps_s *sn1_dma_map = NULL;
+
+	/*
+	 * Darn, we need to get the maps allocated for this bus.
+	 */
+	for (i=0; i<512; i++) {
+		if (busnum_to_pcibr_vhdl[i] == pci_bus) {
+			sn1_dma_map = busnum_to_atedmamaps[i];
+		}
+	}
+
+	/*
+	 * Now get a free dmamap entry from this list.
+	 */
+	for (i=0; i<512; i++, sn1_dma_map++) {
+		if (!sn1_dma_map->dma_addr) {
+			sn1_dma_map->dma_addr = -1;
+			return( (pciio_dmamap_t) sn1_dma_map );
+		}
+	}
+
+printk("get_pciio_dmamap: Unable to find a free dmamap\n");
+	return(NULL);
+
+}
+
+struct sn1_dma_maps_s *
+find_sn1_dma_map(dma_addr_t dma_addr, unsigned char busnum)
+{
+
+	struct sn1_dma_maps_s *sn1_dma_map = NULL;
+	int i;
+
+	sn1_dma_map = busnum_to_atedmamaps[busnum];
+
+	for (i=0; i<512; i++, sn1_dma_map++) {
+		if (sn1_dma_map->dma_addr == dma_addr) {
+			return( sn1_dma_map );
+		}
+	}
+
+printk("find_pciio_dmamap: Unable find the corresponding dma map\n");
+	return(NULL);
+
+}
+
 /*
  * sn1 platform specific pci_alloc_consistent()
  *
@@ -74,7 +127,7 @@
 	device_sysdata = (struct sn1_device_sysdata *) hwdev->sysdata;
 	vhdl = device_sysdata->vhdl;
 
-        if ( ret = (void *)__get_free_pages(gfp, get_order(size)) ) {
+        if ( (ret = (void *)__get_free_pages(gfp, get_order(size))) ) {
 		memset(ret, 0, size);
 	} else {
 		return(NULL);
@@ -142,6 +195,8 @@
 	dma_addr_t dma_addr;
 	paddr_t temp_ptr;
 	struct sn1_device_sysdata *device_sysdata;
+	pciio_dmamap_t dma_map;
+
 
 
 	if (direction == PCI_DMA_NONE)
@@ -153,7 +208,7 @@
 	device_sysdata = (struct sn1_device_sysdata *) hwdev->sysdata;
 	vhdl = device_sysdata->vhdl;
 	for (i = 0; i < nents; i++, sg++) {
-		sg->orig_address = sg->address;
+		sg->orig_address = (char *)NULL;
 		dma_addr = 0;
 		temp_ptr = (paddr_t) __pa(sg->address);
 
@@ -166,7 +221,6 @@
 				PCIBR_BARRIER | PCIIO_BYTE_STREAM |
 				PCIIO_DMA_CMD | PCIIO_DMA_A64 );
 			sg->address = (char *)dma_addr;
-/* printk("pci_map_sg: 64Bits hwdev %p DMA Address 0x%p alt_address 0x%p orig_address 0x%p length 0x%x\n", hwdev, sg->address, sg->alt_address, sg->orig_address, sg->length); */
 			continue;
 		}
 
@@ -180,17 +234,28 @@
 				PCIIO_DMA_CMD);
 			if (dma_addr) {
 				sg->address = (char *)dma_addr;
-/* printk("pci_map_single: 32Bit direct pciio_dmatrans_addr pcidev %p returns dma_addr 0x%lx\n", hwdev, dma_addr); */
 				continue;
-			} else {
-				/*
-				 * We need to map this request by using ATEs.
-				 */
-				printk("pci_map_single: 32Bits DMA Page Map support not available yet!");
-				BUG();
-
 			}
+
 		}
+
+		/*
+		 * It is a 32bit card and we cannot do Direct mapping.
+		 * Let's 32Bit Page map the request.
+		 */
+		dma_map = NULL;
+		dma_map = pciio_dmamap_alloc(vhdl, NULL, sg->length, 
+				PCIBR_BARRIER | PCIIO_BYTE_STREAM |
+				PCIIO_DMA_CMD);
+		if (!dma_map) {
+			printk("pci_map_sg: Unable to allocate anymore 32Bits Page Map entries.\n");
+			BUG();
+		}
+		dma_addr = (dma_addr_t)pciio_dmamap_addr(dma_map, temp_ptr, sg->length);
+		/* printk("pci_map_sg: dma_map 0x%p Phys Addr 0x%p dma_addr 0x%p\n", dma_map, temp_ptr, dma_addr); */
+		sg->address = (char *)dma_addr;
+		sg->orig_address = (char *)dma_map;
+		
 	}
 
 	return nents;
@@ -206,13 +271,25 @@
 sn1_pci_unmap_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
 {
 	int i;
+	struct sn1_dma_maps_s *sn1_dma_map;
+
 
 	if (direction == PCI_DMA_NONE)
 		BUG();
+
 	for (i = 0; i < nelems; i++, sg++)
-		if (sg->orig_address != sg->address) {
+		if (sg->orig_address) {
+			/*
+			 * We maintain the DMA Map pointer in sg->orig_address if 
+			 * it is ever allocated.
+			 */
 			/* phys_to_virt((dma_addr_t)sg->address | ~0x80000000); */
-			sg->address = sg->orig_address;
+			/* sg->address = sg->orig_address; */
+			sg->address = (char *)-1;
+			sn1_dma_map = (struct sn1_dma_maps_s *)sg->orig_address;
+			pciio_dmamap_done((pciio_dmamap_t)sn1_dma_map);
+			pciio_dmamap_free((pciio_dmamap_t)sn1_dma_map);
+			sn1_dma_map->dma_addr = 0;
 			sg->orig_address = 0;
 		}
 }
@@ -234,24 +311,20 @@
 	dma_addr_t dma_addr;
 	paddr_t temp_ptr;
 	struct sn1_device_sysdata *device_sysdata;
+	pciio_dmamap_t dma_map = NULL;
+	struct sn1_dma_maps_s *sn1_dma_map;
 
 
 	if (direction == PCI_DMA_NONE)
 		BUG();
 
-	if (IS_PCI32L(hwdev)) {
-		/*
-		 * SNIA64 cannot support DMA Addresses smaller than 32 bits.
-		 */
-		return ((dma_addr_t) NULL);
-	}
 
 	/*
 	 * find vertex for the device
 	 */
 	device_sysdata = (struct sn1_device_sysdata *)hwdev->sysdata;
 	vhdl = device_sysdata->vhdl;
-/* printk("pci_map_single: Called vhdl = 0x%p ptr = 0x%p size = %d\n", vhdl, ptr, size); */
+
 	/*
 	 * Call our dmamap interface
 	 */
@@ -266,7 +339,6 @@
 			temp_ptr, size,
 			PCIBR_BARRIER | PCIIO_BYTE_STREAM | PCIIO_DMA_CMD
 			| PCIIO_DMA_A64 );
-/* printk("pci_map_single: 64Bit pciio_dmatrans_addr pcidev %p returns dma_addr 0x%lx\n", hwdev, dma_addr); */
 		return (dma_addr);
 	}
 
@@ -281,14 +353,7 @@
 			temp_ptr, size,
 			PCIBR_BARRIER | PCIIO_BYTE_STREAM | PCIIO_DMA_CMD);
 		if (dma_addr) {
-/* printk("pci_map_single: 32Bit direct pciio_dmatrans_addr pcidev %p returns dma_addr 0x%lx\n", hwdev, dma_addr); */
 			return (dma_addr);
-		} else {
-			/*
-			 * We need to map this request by using ATEs.
-			 */
-			printk("pci_map_single: 32Bits DMA Page Map support not available yet!");
-			BUG();
 		}
 	}
 
@@ -297,23 +362,56 @@
 		 * SNIA64 cannot support DMA Addresses smaller than 32 bits.
 		 */
 		return ((dma_addr_t) NULL);
+        }
+
+	/*
+	 * It is a 32bit card and we cannot do Direct mapping.
+	 * Let's 32Bit Page map the request.
+	 */
+	dma_map = NULL;
+	dma_map = pciio_dmamap_alloc(vhdl, NULL, size, PCIBR_BARRIER | 
+			PCIIO_BYTE_STREAM | PCIIO_DMA_CMD);
+	if (!dma_map) {
+		printk("pci_map_single: Unable to allocate anymore 32Bits Page Map entries.\n");
+		BUG();
 	}
 
-	return ((dma_addr_t) NULL);
+	dma_addr = (dma_addr_t) pciio_dmamap_addr(dma_map, temp_ptr, size);
+	/* printk("pci_map_single: dma_map 0x%p Phys Addr 0x%p dma_addr 0x%p\n", dma_map, 
+		temp_ptr, dma_addr); */
+	sn1_dma_map = (struct sn1_dma_maps_s *)dma_map;
+	sn1_dma_map->dma_addr = dma_addr;
 
+	return ((dma_addr_t)dma_addr);
 }
 
 void
 sn1_pci_unmap_single (struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction)
 {
+
+	struct sn1_dma_maps_s *sn1_dma_map = NULL;
+
         if (direction == PCI_DMA_NONE)
-                BUG();
-        /* Nothing to do */
+		BUG();
+
+	/*
+	 * Get the sn1_dma_map entry.
+	 */
+	if (IS_PCI32_MAPPED(dma_addr))
+		sn1_dma_map = find_sn1_dma_map(dma_addr, hwdev->bus->number);
+
+	if (sn1_dma_map) {
+		pciio_dmamap_done((pciio_dmamap_t)sn1_dma_map);
+		pciio_dmamap_free((pciio_dmamap_t)sn1_dma_map);
+		sn1_dma_map->dma_addr = (dma_addr_t)NULL;
+	}
+
 }
 
 void
 sn1_pci_dma_sync_single (struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction)
 {
+	
         if (direction == PCI_DMA_NONE)
                 BUG();
         /* Nothing to do */
@@ -330,5 +428,5 @@
 unsigned long
 sn1_dma_address (struct scatterlist *sg)
 {
-	return (sg->address);
+	return ((unsigned long)sg->address);
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/pciba.c linux/arch/ia64/sn/io/pciba.c
--- v2.4.3/linux/arch/ia64/sn/io/pciba.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/io/pciba.c	Thu Apr 12 12:16:35 2001
@@ -0,0 +1,1716 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2000 by Colin Ngam
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/pci/pci_defs.h>
+#include <asm/sn/prio.h>
+#include <asm/sn/ioerror_handling.h>
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/ioc3.h>
+#include <asm/sn/eeprom.h>
+#include <asm/sn/sn1/bedrock.h>
+#include <asm/sn/sn_private.h>
+#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
+#include <asm/sn/sn1/hubio.h>
+#include <asm/sn/sn1/hubio_next.h>
+#endif
+
+#define copyin(_a, _b, _c)	copy_from_user(_b, _a, _c)
+
+#ifndef	DEBUG_PCIBA
+#define	DEBUG_PCIBA		0
+#endif
+
+/* v_mapphys does not percolate page offset back. */
+#define	PCIBA_ALIGN_CHECK	1
+
+#include <asm/sn/pci/pciba.h>
+
+/* grab an unused space code for "User DMA" space */
+#ifndef	PCIBA_SPACE_UDMA
+#define	PCIBA_SPACE_UDMA	(14)
+#endif
+
+#if DEBUG_REFCT
+extern int		hwgraph_vertex_refct(vertex_hdl_t);
+#endif
+extern int		pci_user_dma_max_pages;
+
+#define NEW(ptr)	(ptr = kmem_zalloc(sizeof (*(ptr)), KM_SLEEP))
+#define DEL(ptr)	(kfree(ptr))
+
+/* Oops -- no standard "pci address" type! */
+typedef uint64_t        pciaddr_t;
+
+/* ================================================================
+ *            driver types
+ */
+typedef struct pciba_slot_s *pciba_slot_t;
+typedef struct pciba_comm_s *pciba_comm_t;
+typedef struct pciba_soft_s *pciba_soft_t;
+typedef struct pciba_map_s *pciba_map_t, **pciba_map_h;
+typedef struct pciba_dma_s *pciba_dma_t, **pciba_dma_h;
+typedef struct pciba_bus_s *pciba_bus_t;
+
+#define	TRACKED_SPACES	16
+struct pciba_comm_s {
+    devfs_handle_t	    conn;
+    pciba_bus_t             bus;
+    int			    refct;
+    pciba_soft_t	    soft[TRACKED_SPACES][2];
+    struct semaphore        lock;
+    pciba_dma_t             dmap;
+};
+
+/* pciba_soft: device_info() for all openables */
+struct pciba_soft_s {
+    pciba_comm_t	    comm;
+    devfs_handle_t          vhdl;
+    int			    refct;
+    pciio_space_t           space;
+    size_t                  size;
+    pciio_space_t           iomem;
+    pciaddr_t               base;
+    unsigned		    flags;
+};
+
+#define	pciba_soft_get(v)	(pciba_soft_t)hwgraph_fastinfo_get(v)
+#define	pciba_soft_set(v,i)	hwgraph_fastinfo_set(v,(arbitrary_info_t)(i))
+
+#define	pciba_soft_lock(soft)	down(&soft->comm->lock)
+#define	pciba_soft_unlock(soft)	up(&soft->comm->lock)
+
+/* pciba_map: data describing a mapping.
+ * (ie. a user mmap request)
+ */
+struct pciba_map_s {
+    pciba_map_t             next;
+#ifdef LATER
+    uthread_t              *uthread;
+#endif
+    __psunsigned_t          handle;
+    uvaddr_t                uvaddr;
+    size_t                  size;
+    pciio_piomap_t          map;
+    pciio_space_t           space;
+    pciaddr_t               base;
+    unsigned		    flags;
+};
+
+/* pciba_dma: data describing a DMA mapping.
+ */
+struct pciba_dma_s {
+    pciba_dma_t             next;
+    iopaddr_t               paddr;	/* starting phys addr */
+    caddr_t                 kaddr;	/* starting kern addr */
+    pciio_dmamap_t          map;	/* mapping resources (ugh!) */
+    pciaddr_t               daddr;	/* starting pci addr */
+    size_t                  pages;	/* size of block in pages */
+    size_t                  bytes;	/* size of block in bytes */
+    __psunsigned_t          handle;	/* mapping handle */
+};
+
+/* pciba_bus: common bus info for all openables
+ * descended from the same master vertex.
+ */
+struct pciba_bus_s {
+    struct semaphore        lock;
+    pciba_map_t             maps;	/* stack of mappings */
+    int			    refct;
+};
+
+#define	pciba_bus_lock(bus)	down(&bus->lock)
+#define	pciba_bus_unlock(bus)	up(&bus->lock)
+
+typedef union ioctl_arg_buffer_u {
+    char                    data[IOCPARM_MASK + 1];
+    uint8_t                 uc;
+    uint16_t                us;
+    uint32_t                ui;
+    uint64_t                ud;
+    caddr_t                 ca;
+#if ULI
+    struct uliargs          uli;
+    struct uliargs32	    uli32;
+#endif
+} ioctl_arg_buffer_t;
+
+/* ================================================================
+ *            driver variables
+ */
+char                   *pciba_mversion = "mload version 7.0";
+int                     pciba_devflag = 0x1 |
+                                        0x200 |
+                                        0x400;
+
+/* this counts the reasons why we can not
+ * currently unload this driver.
+ */
+atomic_t                pciba_prevent_unload = ATOMIC_INIT(0);
+
+#if DEBUG_PCIBA
+static struct reg_values space_v[] =
+{
+    {PCIIO_SPACE_NONE, "none"},
+    {PCIIO_SPACE_ROM, "ROM"},
+    {PCIIO_SPACE_IO, "I/O"},
+    {PCIIO_SPACE_MEM, "MEM"},
+    {PCIIO_SPACE_MEM32, "MEM(32)"},
+    {PCIIO_SPACE_MEM64, "MEM(64)"},
+    {PCIIO_SPACE_CFG, "CFG"},
+    {PCIIO_SPACE_WIN(0), "WIN(0)"},
+    {PCIIO_SPACE_WIN(1), "WIN(1)"},
+    {PCIIO_SPACE_WIN(2), "WIN(2)"},
+    {PCIIO_SPACE_WIN(3), "WIN(3)"},
+    {PCIIO_SPACE_WIN(4), "WIN(4)"},
+    {PCIIO_SPACE_WIN(5), "WIN(5)"},
+    {PCIBA_SPACE_UDMA, "UDMA"},
+    {PCIIO_SPACE_BAD, "BAD"},
+    {0}
+};
+
+static struct reg_desc  space_desc[] =
+{
+    {0xFF, 0, "space", 0, space_v},
+    {0}
+};
+#endif
+
+char                    pciba_edge_lbl_base[] = "base";
+char                    pciba_edge_lbl_cfg[] = "config";
+char                    pciba_edge_lbl_dma[] = "dma";
+char                    pciba_edge_lbl_intr[] = "intr";
+char                    pciba_edge_lbl_io[] = "io";
+char                    pciba_edge_lbl_mem[] = "mem";
+char                    pciba_edge_lbl_rom[] = "rom";
+char                   *pciba_edge_lbl_win[6] =
+{"0", "1", "2", "3", "4", "5"};
+
+#define	PCIBA_EDGE_LBL_BASE	pciba_edge_lbl_base
+#define	PCIBA_EDGE_LBL_CFG	pciba_edge_lbl_cfg
+#define	PCIBA_EDGE_LBL_DMA	pciba_edge_lbl_dma
+#define	PCIBA_EDGE_LBL_INTR	pciba_edge_lbl_intr
+#define	PCIBA_EDGE_LBL_IO	pciba_edge_lbl_io
+#define	PCIBA_EDGE_LBL_MEM	pciba_edge_lbl_mem
+#define	PCIBA_EDGE_LBL_ROM	pciba_edge_lbl_rom
+#define	PCIBA_EDGE_LBL_WIN(n)	pciba_edge_lbl_win[n]
+
+#define	PCIBA_EDGE_LBL_FLIP	pciba_edge_lbl_flip
+
+static char             pciba_info_lbl_bus[] = "pciba_bus";
+
+#define	PCIBA_INFO_LBL_BUS	pciba_info_lbl_bus
+
+struct file_operations pciba_fops = {
+	owner:	THIS_MODULE,
+	llseek: NULL,
+	read: NULL,
+	write: NULL,
+	readdir: NULL,
+	poll: NULL,
+	ioctl: NULL,
+	mmap: NULL,
+	open: NULL,
+	flush: NULL,
+	release: NULL,
+	fsync: NULL,
+	fasync: NULL,
+	lock: NULL,
+	readv: NULL,
+	writev: NULL
+};
+	
+/* ================================================================
+ *            function table of contents
+ */
+
+void                    pciba_init(void);
+int                     pciba_attach(devfs_handle_t);
+
+static void		pciba_sub_attach(pciba_comm_t,
+					 pciio_space_t, pciio_space_t, pciaddr_t,
+					 devfs_handle_t, devfs_handle_t, char *);
+
+static pciba_bus_t      pciba_find_bus(devfs_handle_t, int);
+#ifdef LATER
+static void             pciba_map_push(pciba_bus_t, pciba_map_t);
+static pciba_map_t      pciba_map_pop_hdl(pciba_bus_t, __psunsigned_t);
+static void             pciba_sub_detach(devfs_handle_t, char *);
+static pciio_iter_f     pciba_unload_me;
+#endif
+
+int                     pciba_unload(void);
+int                     pciba_unreg(void);
+int                     pciba_detach(devfs_handle_t);
+
+int                     pciba_open(dev_t *, int, int, struct cred *);
+int                     pciba_close(dev_t);
+int                     pciba_read(dev_t, cred_t *);
+int                     pciba_write(dev_t, cred_t *);
+int                     pciba_ioctl(dev_t, int, void *, int, cred_t *, int *);
+
+int                     pciba_map(dev_t, vhandl_t *, off_t, size_t, uint32_t);
+int                     pciba_unmap(dev_t, vhandl_t *);
+
+#if ULI
+void                    pciba_clearuli(struct uli *);
+static intr_func_f      pciba_intr;
+#endif /* Undef as it gets implemented */
+
+/* ================================================================
+ *            driver load, register, and setup
+ */
+void
+pciba_init(void)
+{
+
+	/*
+	 * What do we need to do here?
+	 */
+#if DEBUG_PCIBA
+    printk("pciba_init()\n");
+#endif
+}
+
+#ifdef LATER
+#if HWG_PERF_CHECK && IP30 && !DEBUG
+void
+pciba_timeout(void *arg1, void *arg2)
+{
+    struct semaphore       *semap = (sema_t *) arg1;
+    unsigned long          *cvalp = (unsigned long *) arg2;
+
+    if (cvalp)
+	cvalp[0] = RAW_COUNT();
+    if (semap)
+	up(semap);
+}
+
+volatile unsigned long  cNval[1];
+struct semaphore        tsema;
+
+void
+pciba_timeout_test(void)
+{
+    unsigned long           c0val, cval;
+    toid_t                  tid;
+
+    extern void             hwg_hprint(unsigned long, char *);
+
+    sema_init(&tsema, 0);
+
+    cNval[0] = 0;
+    c0val = RAW_COUNT();
+    tid = timeout((void (*)()) pciba_timeout, (void *) 0, 1, (void *) cNval);
+    DELAY(1000000);
+    cval = cNval[0];
+    if (cval == 0) {
+	untimeout(tid);
+	PRINT_ALERT("pciba: one-tick timeout did not happen in a second\n");
+	return;
+    }
+    cval = cval - c0val;
+    hwg_hprint(cval, "timeout(1)");
+
+    cNval[0] = 0;
+    c0val = RAW_COUNT();
+    tid = timeout((void (*)()) pciba_timeout, (void *) &tsema, 2, (void *) cNval);
+
+    /* FIXME : this probably needs to be down_interruptible() */
+
+    if (down(&tsema) < 0) {	/* wait for the pciba_timeout */
+	untimeout(tid);
+	PRINT_WARNING("pciba: timeout(2) time check aborted\n");
+	return;
+    }
+    cval = cNval[0];
+    if (cval == 0) {
+	untimeout(tid);
+	PRINT_WARNING("pciba: timeout(2) time not logged\n");
+	return;
+    }
+    cval = cval - c0val;
+    hwg_hprint(cval, "timeout(2)");
+
+    cNval[0] = 0;
+    c0val = RAW_COUNT();
+    tid = timeout((void (*)()) pciba_timeout, (void *) &tsema, HZ, (void *) cNval);
+
+    /* FIXME : this probably needs to be down_interruptible() */
+
+    if (down(&tsema) < 0) {	/* wait for the pciba_timeout */
+	untimeout(tid);
+	PRINT_WARNING("pciba: timeout(HZ) time check aborted\n");
+	return;
+    }
+    cval = cNval[0];
+    if (cval == 0) {
+	untimeout(tid);
+	PRINT_WARNING("pciba: timeout(HZ) time not logged\n");
+	return;
+    }
+    cval = cval - c0val;
+    hwg_hprint(cval, "timeout(HZ)");
+
+    printk("verifying untimeout() cancells ...\n");
+    cNval[0] = 0;
+    tid = timeout((void (*)()) pciba_timeout, (void *) 0, 2, (void *) cNval);
+    untimeout(tid);
+    DELAY(1000000);
+    cval = cNval[0];
+    if (cval != 0) {
+	PRINT_ALERT("pciba: unable to cancel two-tick timeout\n");
+	cval -= c0val;
+	hwg_hprint(cval, "CANCELLED timeout(2)");
+    }
+}
+#endif
+
+int
+pciba_reg(void)
+{
+#if DEBUG_PCIBA
+    printk("pciba_reg()\n");
+#endif
+    pciio_driver_register(-1, -1, "pciba_", 0);
+
+#if HWG_PERF_CHECK && IP30 && !DEBUG
+    printk("%s %d\n", __FUNCTION__, __LINE__);
+pciba_timeout_test();
+#endif
+
+#if DEBUG_REFCT
+    {
+	char	       *cname = "pciba";
+	char	       *dname = "ptv";
+	char           *cpath0 = "node/xtalk/15";
+	char           *uname0 = "0";
+	char           *cpath1 = "node/xtalk/13";
+	char           *uname1 = "1";
+	devfs_handle_t conn;
+	devfs_handle_t conv;
+	devfs_handle_t vhdl;
+	int		ret;
+
+	printk("pciba refct tests:\n");
+
+#define	SHOWREF(vhdl,func)	printk("ref=%d\t%s\t(%d) %v\n", hwgraph_vertex_refct(vhdl), #func, vhdl, vhdl);
+
+	if (GRAPH_SUCCESS != (ret = hwgraph_path_add(hwgraph_root, cname, &conv)))
+	    printk("\tunable to create conv (ret=%d)\n", ret);
+	else {						SHOWREF(conv, hwgraph_path_add);
+	    if (GRAPH_SUCCESS != (ret = hwgraph_traverse(hwgraph_root, cpath0, &conn)))
+		printk("\tunable to find %s (ret=%d)\n", cpath0, ret);
+	    else {					SHOWREF(conn, hwgraph_traverse);
+		if (GRAPH_SUCCESS != (ret = hwgraph_char_device_add(conn, dname, "pciba_", &vhdl)))
+		    printk("unable to create %v/%s (ret=%d)\n", conn, dname, ret);
+		else {					SHOWREF(vhdl, hwgraph_char_device_add);
+		    hwgraph_chmod(vhdl, 0666);		SHOWREF(vhdl, hwgraph_chmod);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_edge_add(conv, vhdl, uname0)))
+			printk("unable to create %v/%s (ret=%d)\n", conn, uname0, vhdl, ret);
+		    else				SHOWREF(vhdl, hwgraph_edge_add);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(vhdl)))
+			printk("unable to unref %v\n", vhdl);
+		    else				SHOWREF(vhdl, hwgraph_vertex_unref);
+		}
+		if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conn)))
+		    printk("unable to unref %v\n", conn);
+		else					SHOWREF(conn, hwgraph_vertex_unref);
+	    }
+ 
+	    if (GRAPH_SUCCESS != (ret = hwgraph_traverse(hwgraph_root, cpath1, &conn)))
+		printk("\tunable to find %s (ret=%d)\n", cpath1, ret);
+	    else {					SHOWREF(conn, hwgraph_traverse);
+		if (GRAPH_SUCCESS != (ret = hwgraph_char_device_add(conn, dname, "pciba_", &vhdl)))
+		    printk("unable to create %v/%s (ret=%d)\n", conn, dname, ret);
+		else {					SHOWREF(vhdl, hwgraph_char_device_add);
+		    hwgraph_chmod(vhdl, 0666);		SHOWREF(vhdl, hwgraph_chmod);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_edge_add(conv, vhdl, uname1)))
+			printk("unable to create %v/%s (ret=%d)\n", conn, uname1, vhdl, ret);
+		    else				SHOWREF(vhdl, hwgraph_edge_add);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(vhdl)))
+			printk("unable to unref %v\n", vhdl);
+		    else				SHOWREF(vhdl, hwgraph_vertex_unref);
+		}
+		if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conn)))
+		    printk("unable to unref %v\n", conn);
+		else					SHOWREF(conn, hwgraph_vertex_unref);
+	    }
+ 
+	    if (GRAPH_SUCCESS != (ret = hwgraph_traverse(hwgraph_root, cpath0, &conn)))
+		printk("\tunable to find %s (ret=%d)\n", cpath0, ret);
+	    else {					SHOWREF(conn, hwgraph_traverse);
+		if (GRAPH_SUCCESS != (ret = hwgraph_traverse(conn, dname, &vhdl)))
+		    printk("\tunable to find %v/%s (ret=%d)\n", conn, dname, ret);
+		else {					SHOWREF(vhdl, hwgraph_traverse);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(conv, uname0, NULL)))
+			printk("\tunable to remove edge %v/%s (ret=%d)\n", conv, uname0, ret);
+		    else				SHOWREF(vhdl, hwgraph_edge_remove);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(conn, dname, NULL)))
+			printk("\tunable to remove edge %v/%s (ret=%d)\n", conn, dname, ret);
+		    else				SHOWREF(vhdl, hwgraph_edge_remove);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(vhdl)))
+			printk("unable to unref %v\n", vhdl);
+		    else				SHOWREF(vhdl, hwgraph_vertex_unref);
+		    if (GRAPH_SUCCESS == (ret = hwgraph_vertex_destroy(vhdl)))
+			printk("\tvertex %d destroyed OK\n", vhdl);
+		    else				SHOWREF(vhdl, hwgraph_vertex_destroy);
+		}
+		if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conn)))
+		    printk("unable to unref %v\n", conn);
+		else					SHOWREF(conn, hwgraph_vertex_unref);
+	    }
+
+	    if (GRAPH_SUCCESS != (ret = hwgraph_traverse(hwgraph_root, cpath1, &conn)))
+		printk("\tunable to find %s (ret=%d)\n", cpath1, ret);
+	    else {					SHOWREF(conn, hwgraph_traverse);
+		if (GRAPH_SUCCESS != (ret = hwgraph_traverse(conn, dname, &vhdl)))
+		    printk("\tunable to find %v/%s (ret=%d)\n", conn, dname, ret);
+		else {					SHOWREF(vhdl, hwgraph_traverse);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(conv, uname1, NULL)))
+			printk("\tunable to remove edge %v/%s (ret=%d)\n", conv, uname1, ret);
+		    else				SHOWREF(vhdl, hwgraph_edge_remove);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(conn, dname, NULL)))
+			printk("\tunable to remove edge %v/%s (ret=%d)\n", conn, dname, ret);
+		    else				SHOWREF(vhdl, hwgraph_edge_remove);
+		    if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(vhdl)))
+			printk("unable to unref %v\n", vhdl);
+		    else				SHOWREF(vhdl, hwgraph_vertex_unref);
+		    if (GRAPH_SUCCESS == (ret = hwgraph_vertex_destroy(vhdl)))
+			printk("\tvertex %d destroyed OK\n", vhdl);
+		    else				SHOWREF(vhdl, hwgraph_vertex_destroy);
+		}
+		if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conn)))
+		    printk("unable to unref %v\n", conn);
+		else					SHOWREF(conn, hwgraph_vertex_unref);
+	    }
+
+	    if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(hwgraph_root, cname, NULL)))
+		printk("\tunable to remove edge %v/%s (ret=%d)\n", hwgraph_root, cname, ret);
+	    else				SHOWREF(conv, hwgraph_edge_remove);
+	    if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conv)))
+		printk("unable to unref %v\n", conv);
+	    else					SHOWREF(conv, hwgraph_vertex_unref);
+	    if (GRAPH_SUCCESS == (ret = hwgraph_vertex_destroy(conv)))
+		printk("\tvertex %d destroyed OK\n", conv);
+	    else					SHOWREF(conv, hwgraph_vertex_destroy);
+	}
+    }
+#endif
+
+    return 0;
+}
+
+#endif
+int
+pciba_attach(devfs_handle_t hconn)
+{
+#if defined(PCIIO_SLOT_NONE)
+    pciio_info_t            info = pciio_info_get(hconn);
+    pciio_slot_t            slot = pciio_info_slot_get(info);
+#endif
+    pciba_comm_t	    comm;
+    pciba_bus_t             bus;
+    int                     ht;
+    devfs_handle_t	    hbase;
+    devfs_handle_t          gconn;
+    devfs_handle_t          gbase;
+    int                     win;
+    int                     wins;
+    pciio_space_t           space;
+    pciaddr_t               base;
+
+    int                     iwins;
+    int                     mwins;
+
+#if DEBUG_PCIBA
+    printk("pciba_attach(%p)\n", hconn);
+#endif
+
+    /* Pick up "dualslot guest" vertex,
+     * which gets all functionality except
+     * config space access.
+     */
+    if ((GRAPH_SUCCESS !=
+	 hwgraph_traverse(hconn, ".guest", &gconn)) ||
+	(hconn == gconn))
+	gconn = GRAPH_VERTEX_NONE;
+
+    bus = pciba_find_bus(hconn, 1);
+    bus->refct ++;
+
+    /* set up data common to all pciba openables
+     * on this connection point.
+     */
+    NEW(comm);
+    comm->conn = hconn;
+    comm->bus = bus;
+    comm->refct = 0;
+    sema_init(&comm->lock, 1);
+
+#if !defined(PCIIO_SLOT_NONE)
+    if (bus->refct == 1)
+#else
+    if (slot == PCIIO_SLOT_NONE)
+#endif
+    {
+	pciio_info_t            pciio_info;
+	devfs_handle_t          master;
+
+	pciio_info = pciio_info_get(hconn);
+	master = pciio_info_master_get(pciio_info);
+
+	pciba_sub_attach(comm, PCIIO_SPACE_IO, PCIIO_SPACE_IO, 0, master, master, PCIBA_EDGE_LBL_IO);
+	pciba_sub_attach(comm, PCIIO_SPACE_MEM, PCIIO_SPACE_MEM, 0, master, master, PCIBA_EDGE_LBL_MEM);
+#if defined(PCIIO_SLOT_NONE)
+	return 0;
+#endif
+    }
+
+    ht = 0x7F & pciio_config_get(hconn, PCI_CFG_HEADER_TYPE, 1);
+
+    wins = ((ht == 0x00) ? 6 :
+	    (ht == 0x01) ? 2 :
+	    0);
+
+    mwins = iwins = 0;
+
+    hbase = GRAPH_VERTEX_NONE;
+    gbase = GRAPH_VERTEX_NONE;
+
+    for (win = 0; win < wins; win++) {
+
+	base = pciio_config_get(hconn, PCI_CFG_BASE_ADDR(win), 4);
+	if (base & 1) {
+	    space = PCIIO_SPACE_IO;
+	    base &= 0xFFFFFFFC;
+	} else if ((base & 7) == 4) {
+	    space = PCIIO_SPACE_MEM;
+	    base &= 0xFFFFFFF0;
+	    base |= ((pciaddr_t) pciio_config_get(hconn, PCI_CFG_BASE_ADDR(win + 1), 4)) << 32;
+	} else {
+	    space = PCIIO_SPACE_MEM;
+	    base &= 0xFFFFFFF0;
+	}
+
+	if (!base)
+	    break;
+
+#if PCIBA_ALIGN_CHECK
+	if (base & (_PAGESZ - 1)) {
+#if DEBUG_PCIBA
+	    PRINT_WARNING("%p pciba: BASE%d not page aligned!\n"
+		    "\tmmap this window at offset 0x%x via \".../pci/%s\"\n",
+		    hconn, win, base,
+		    (space == PCIIO_SPACE_IO) ? "io" : "mem");
+#endif
+	    continue;			/* next window */
+	}
+#endif
+
+	if ((hbase == GRAPH_VERTEX_NONE) &&
+	    ((GRAPH_SUCCESS !=
+	      hwgraph_path_add(hconn, PCIBA_EDGE_LBL_BASE, &hbase)) ||
+	     (hbase == GRAPH_VERTEX_NONE)))
+	    break;			/* no base vertex, no more windows. */
+
+	if ((gconn != GRAPH_VERTEX_NONE) &&
+	    (gbase == GRAPH_VERTEX_NONE) &&
+	    ((GRAPH_SUCCESS !=
+	      hwgraph_path_add(gconn, PCIBA_EDGE_LBL_BASE, &gbase)) ||
+	     (gbase == GRAPH_VERTEX_NONE)))
+	    break;			/* no base vertex, no more windows. */
+
+	pciba_sub_attach(comm, PCIIO_SPACE_WIN(win), space, base, hbase, gbase, PCIBA_EDGE_LBL_WIN(win));
+
+	if (space == PCIIO_SPACE_IO) {
+	    if (!iwins++) {
+		pciba_sub_attach(comm, PCIIO_SPACE_WIN(win), space, base, hconn, gconn, PCIBA_EDGE_LBL_IO);
+	    }
+	} else {
+	    if (!mwins++) {
+		pciba_sub_attach(comm, PCIIO_SPACE_WIN(win), space, base, hconn, gconn, PCIBA_EDGE_LBL_MEM);
+	    }
+	}
+
+	if ((base & 7) == 4)
+	    win++;
+    }
+
+    pciba_sub_attach(comm, PCIIO_SPACE_CFG, PCIIO_SPACE_NONE, 0, hconn, gconn, PCIBA_EDGE_LBL_CFG);
+    pciba_sub_attach(comm, PCIBA_SPACE_UDMA, PCIIO_SPACE_NONE, 0, hconn, gconn, PCIBA_EDGE_LBL_DMA);
+#if ULI
+    pciba_sub_attach(comm, PCIIO_SPACE_NONE, PCIIO_SPACE_NONE, 0, hconn, gconn, PCIBA_EDGE_LBL_INTR);
+#endif
+
+    /* XXX should ignore if device is an IOC3 */
+    if (ht == 0x01)
+	base = pciio_config_get(hconn, PCI_EXPANSION_ROM+8, 4);
+    else
+	base = pciio_config_get(hconn, PCI_EXPANSION_ROM, 4);
+
+    base &= 0xFFFFF000;
+
+    if (base) {
+	if (base & (_PAGESZ - 1))
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+	    PRINT_WARNING("%v pciba: ROM is 0x%x\n"
+		    "\tnot page aligned, mmap will be difficult\n",
+		    hconn, base);
+#else
+	    PRINT_WARNING("0x%x pciba: ROM is 0x%x\n"
+		    "\tnot page aligned, mmap will be difficult\n",
+		    hconn, base);
+#endif
+	pciba_sub_attach(comm, PCIIO_SPACE_ROM, PCIIO_SPACE_MEM, base, hconn, gconn, PCIBA_EDGE_LBL_ROM);
+    }
+
+#if !FICUS	/* FICUS shorts the refct by one on path_add */
+    if (hbase != GRAPH_VERTEX_NONE)
+	hwgraph_vertex_unref(hbase);
+
+    if (gbase != GRAPH_VERTEX_NONE)
+	hwgraph_vertex_unref(gbase);
+#endif
+
+    return 0;
+}
+
+static void
+pciba_sub_attach2(pciba_comm_t comm,
+		  pciio_space_t space,
+		  pciio_space_t iomem,
+		  pciaddr_t base,
+		  devfs_handle_t from,
+		  char *name,
+		  char *suf,
+		  unsigned bigend)
+{
+    char		nbuf[128];
+    pciba_soft_t            soft;
+    devfs_handle_t	handle = NULL;
+
+    if (suf && *suf) {
+	strcpy(nbuf, name);
+	name = nbuf;
+	strcat(name, suf);
+    }
+
+#if DEBUG_PCIBA
+    printk("pciba_sub_attach2 %p/%s %p at %p[%x]\n",
+	   from, name, space, space_desc, iomem, space_desc, base, from, name);
+#endif
+
+    if (space < TRACKED_SPACES)
+	if ((soft = comm->soft[space][bigend]) != NULL) {
+	    soft->refct ++;
+	    hwgraph_edge_add(from, soft->vhdl, name);
+	    return;
+	}
+
+    NEW(soft);
+    if (!soft)
+	return;
+
+    soft->comm = comm;
+    soft->space = space;
+    soft->size = 0;
+    soft->iomem = iomem;
+    soft->base = base;
+    soft->refct = 1;
+
+    if (space == PCIIO_SPACE_NONE)
+	soft->flags = 0;
+    else if (bigend)
+	soft->flags = PCIIO_BYTE_STREAM;
+    else
+	soft->flags = PCIIO_WORD_VALUES;
+
+    handle = hwgraph_register(from, name,
+		0, DEVFS_FL_AUTO_DEVNUM,
+		0, 0,
+		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+		&pciba_fops, NULL);
+    soft->vhdl = handle;
+    pciba_soft_set(soft->vhdl, soft);
+    if (space < TRACKED_SPACES)
+	comm->soft[space][bigend] = soft;
+    comm->refct ++;
+}
+
+static void
+pciba_sub_attach1(pciba_comm_t comm,
+		  pciio_space_t space,
+		  pciio_space_t iomem,
+		  pciaddr_t base,
+		  devfs_handle_t hfrom,
+		  devfs_handle_t gfrom,
+		  char *name,
+		  char *suf,
+		  unsigned bigend)
+{
+    pciba_sub_attach2(comm, space, iomem, base, hfrom, name, suf, bigend);
+    if ((gfrom != GRAPH_VERTEX_NONE) && (gfrom != hfrom))
+	pciba_sub_attach2(comm, space, iomem, base, gfrom, name, suf, bigend);
+}
+
+static void
+pciba_sub_attach(pciba_comm_t comm,
+		 pciio_space_t space,
+		 pciio_space_t iomem,
+		 pciaddr_t base,
+		 devfs_handle_t hfrom,
+		 devfs_handle_t gfrom,
+		 char *name)
+{
+    pciba_sub_attach1(comm, space, iomem, base, hfrom, gfrom, name, NULL, 0);
+    if (iomem != PCIIO_SPACE_NONE) {
+	pciba_sub_attach1(comm, space, iomem, base, hfrom, gfrom, name, "_le", 0);
+	pciba_sub_attach1(comm, space, iomem, base, hfrom, gfrom, name, "_be", 1);
+    }
+}
+
+#ifdef LATER
+static void
+pciba_reload_me(devfs_handle_t pconn_vhdl)
+{
+    devfs_handle_t            vhdl;
+
+#if DEBUG_PCIBA
+    printf("pciba_reload_me(%v)\n", pconn_vhdl);
+#endif
+
+    if (GRAPH_SUCCESS !=
+	hwgraph_traverse(pconn_vhdl, PCIBA_EDGE_LBL_CFG, &vhdl))
+	return;
+
+    hwgraph_vertex_unref(vhdl);
+}
+#endif	/* LATER */
+
+static                  pciba_bus_t
+pciba_find_bus(devfs_handle_t pconn, int cflag)
+{
+    pciio_info_t            pciio_info;
+    devfs_handle_t          master;
+    arbitrary_info_t        ainfo;
+    pciba_bus_t             bus;
+
+    pciio_info = pciio_info_get(pconn);
+    master = pciio_info_master_get(pciio_info);
+
+    if (GRAPH_SUCCESS ==
+	hwgraph_info_get_LBL(master, PCIBA_INFO_LBL_BUS, &ainfo))
+	return (pciba_bus_t) ainfo;
+
+    if (!cflag)
+	return 0;
+
+    NEW(bus);
+    if (!bus)
+	return 0;
+
+    sema_init(&bus->lock, 1);
+
+    ainfo = (arbitrary_info_t) bus;
+    hwgraph_info_add_LBL(master, PCIBA_INFO_LBL_BUS, ainfo);
+    hwgraph_info_get_LBL(master, PCIBA_INFO_LBL_BUS, &ainfo);
+    if ((pciba_bus_t) ainfo != bus)
+	DEL(bus);
+#if DEBUG_PCIBA
+    else
+	printk("pcbia_find_bus: new bus at %p\n", master);
+#endif
+
+    return (pciba_bus_t) ainfo;
+}
+
+#ifdef LATER
+static void
+pciba_map_push(pciba_bus_t bus, pciba_map_t map)
+{
+#if DEBUG_PCIBA
+    printk("pciba_map_push(bus=0x%x, map=0x%x, hdl=0x%x\n",
+	   bus, map, map->handle);
+#endif
+    pciba_bus_lock(bus);
+    map->next = bus->maps;
+    bus->maps = map;
+    pciba_bus_unlock(bus);
+}
+
+static                  pciba_map_t
+pciba_map_pop_hdl(pciba_bus_t bus, __psunsigned_t handle)
+{
+    pciba_map_h             hdl;
+    pciba_map_t             map;
+
+    pciba_bus_lock(bus);
+    for (hdl = &bus->maps; map = *hdl; hdl = &map->next)
+	if (map->handle == handle) {
+	    *hdl = map->next;
+	    break;
+	}
+    pciba_bus_unlock(bus);
+#if DEBUG_PCIBA
+    printk("pciba_map_pop_va(bus=0x%x, handle=0x%x) returns map=0x%x\n",
+	   bus, handle, map);
+#endif
+    return map;
+}
+
+/* ================================================================
+ *            driver teardown, unregister and unload
+ */
+int
+pciba_unload(void)
+{
+#if DEBUG_PCIBA
+    printk("pciba_unload()\n");
+#endif
+
+    if (atomic_read(&pciba_prevent_unload))
+	return -1;
+
+    pciio_iterate("pciba_", pciba_unload_me);
+
+    return 0;
+}
+
+int
+pciba_unreg(void)
+{
+
+#if DEBUG_PCIBA
+    printf("pciba_unreg()\n");
+#endif
+
+    if (atomic_read(&pciba_prevent_unload))
+	return -1;
+
+    pciio_driver_unregister("pciba_");
+    return 0;
+}
+
+int
+pciba_detach(devfs_handle_t conn)
+{
+    devfs_handle_t          base;
+    pciba_bus_t             bus;
+    devfs_handle_t          gconn;
+    devfs_handle_t          gbase;
+
+    pciio_info_t            pciio_info;
+    devfs_handle_t          master;
+    arbitrary_info_t        ainfo;
+    int			    ret;
+
+#if DEBUG_PCIBA
+    printf("pciba_detach(%v)\n", conn);
+#endif
+
+    if ((GRAPH_SUCCESS !=
+	 hwgraph_traverse(conn, ".guest", &gconn)) ||
+	(conn == gconn))
+	gconn = GRAPH_VERTEX_NONE;
+
+    if (gconn != GRAPH_VERTEX_NONE) {
+	pciba_sub_detach(gconn, PCIBA_EDGE_LBL_CFG);
+	pciba_sub_detach(gconn, PCIBA_EDGE_LBL_DMA);
+	pciba_sub_detach(gconn, PCIBA_EDGE_LBL_ROM);
+#if ULI
+	pciba_sub_detach(gconn, PCIBA_EDGE_LBL_INTR);
+#endif
+	if (GRAPH_SUCCESS == hwgraph_edge_remove(conn, PCIBA_EDGE_LBL_BASE, &gbase)) {
+	    pciba_sub_detach(gconn, PCIBA_EDGE_LBL_MEM);
+	    pciba_sub_detach(gconn, PCIBA_EDGE_LBL_IO);
+	    pciba_sub_detach(gbase, "0");
+	    pciba_sub_detach(gbase, "1");
+	    pciba_sub_detach(gbase, "2");
+	    pciba_sub_detach(gbase, "3");
+	    pciba_sub_detach(gbase, "4");
+	    pciba_sub_detach(gbase, "5");
+	    hwgraph_vertex_unref(gbase);
+	    if (GRAPH_SUCCESS != (ret = hwgraph_vertex_destroy(gbase))) {
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+		PRINT_WARNING("pciba: hwgraph_vertex_destroy(%v/base) failed (%d)",
+			conn, ret);
+#else
+		PRINT_WARNING("pciba: hwgraph_vertex_destroy(0x%x/base) failed (%d)",
+			conn, ret);
+#endif
+#if DEBUG_REFCT
+		printk("\tretained refct %d\n", hwgraph_vertex_refct(gbase));
+#endif
+	    }
+	}
+    }
+
+    pciba_sub_detach(conn, PCIBA_EDGE_LBL_CFG);
+    pciba_sub_detach(conn, PCIBA_EDGE_LBL_DMA);
+    pciba_sub_detach(conn, PCIBA_EDGE_LBL_ROM);
+#if ULI
+    pciba_sub_detach(conn, PCIBA_EDGE_LBL_INTR);
+#endif
+
+    if (GRAPH_SUCCESS == hwgraph_edge_remove(conn, PCIBA_EDGE_LBL_BASE, &base)) {
+	pciba_sub_detach(conn, PCIBA_EDGE_LBL_MEM);
+	pciba_sub_detach(conn, PCIBA_EDGE_LBL_IO);
+	pciba_sub_detach(base, "0");
+	pciba_sub_detach(base, "1");
+	pciba_sub_detach(base, "2");
+	pciba_sub_detach(base, "3");
+	pciba_sub_detach(base, "4");
+	pciba_sub_detach(base, "5");
+	hwgraph_vertex_unref(base);
+	if (GRAPH_SUCCESS != (ret = hwgraph_vertex_destroy(base))) {
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+	    PRINT_WARNING(CE_WARN, "pciba: hwgraph_vertex_destroy(%v/base) failed (%d)",
+		    conn, ret);
+#else
+	    PRINT_WARNING(CE_WARN, "pciba: hwgraph_vertex_destroy(0x%x/base) failed (%d)",
+		    conn, ret);
+#endif
+#if DEBUG_REFCT
+	    printk("\tretained refct %d\n", hwgraph_vertex_refct(base));
+#endif
+	}
+    }
+
+    bus = pciba_find_bus(conn, 0);
+    if (bus && !--(bus->refct)) {
+
+	pciio_info = pciio_info_get(conn);
+
+	master = pciio_info_master_get(pciio_info);
+
+	pciba_sub_detach(master, PCIBA_EDGE_LBL_IO);
+	pciba_sub_detach(master, PCIBA_EDGE_LBL_MEM);
+	pciba_sub_detach(master, PCIBA_EDGE_LBL_CFG);
+	hwgraph_info_remove_LBL(master, PCIBA_INFO_LBL_BUS, &ainfo);
+
+#if DEBUG_PCIBA
+	printf("pcbia_detach: DEL(bus) at %v\n", master);
+#endif
+	DEL(bus);
+    } 
+
+    return 0;
+}
+
+static void
+pciba_sub_detach1(devfs_handle_t conn,
+		  char *name,
+		  char *suf)
+{
+    devfs_handle_t         vhdl;
+    pciba_soft_t            soft;
+    pciba_comm_t	    comm;
+    int			    ret;
+    char		nbuf[128];
+
+    if (suf && *suf) {
+	strcpy(nbuf, name);
+	name = nbuf;
+	strcat(name, suf);
+    }
+
+    if ((GRAPH_SUCCESS == hwgraph_edge_remove(conn, name, &vhdl)) &&
+	((soft = pciba_soft_get(vhdl)) != NULL)) {
+#if DEBUG_PCIBA
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+	prink("pciba_sub_detach(%v,%s)\n", conn, name);
+#else
+	prink("pciba_sub_detach(0x%x,%s)\n", conn, name);
+#endif
+#endif
+
+	hwgraph_vertex_unref(soft->vhdl);
+#if DEBUG_REFCT
+	printk("\tadjusted refct %d (soft ref: %d)\n",
+		hwgraph_vertex_refct(vhdl),
+		soft->refct);
+#endif
+	if (!--(soft->refct)) {
+	    comm = soft->comm;
+	    if (!--(comm->refct)) {
+		DEL(comm);
+	    }
+	    pciba_soft_set(vhdl, 0);
+	    DEL(soft);
+
+	    hwgraph_vertex_unref(vhdl);
+	    if (GRAPH_SUCCESS != (ret = hwgraph_vertex_destroy(vhdl))) {
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+		PRINT_WARNING("pciba: hwgraph_vertex_destroy(0x%x/%s) failed (%d)",
+			conn, name, ret);
+#else
+		PRINT_WARNING("pciba: hwgraph_vertex_destroy(%v/%s) failed (%d)",
+			conn, name, ret);
+#endif
+#if DEBUG_REFCT
+		printk("\tretained refct %d\n", hwgraph_vertex_refct(vhdl));
+#endif
+	    }
+	}
+    }
+}
+
+static void
+pciba_sub_detach(devfs_handle_t conn,
+		 char *name)
+{
+    pciba_sub_detach1(conn, name, "");
+    pciba_sub_detach1(conn, name, "_le");
+    pciba_sub_detach1(conn, name, "_be");
+}
+
+static void
+pciba_unload_me(devfs_handle_t pconn_vhdl)
+{
+    devfs_handle_t         c_vhdl;
+
+#if DEBUG_PCIBA
+    printf("pciba_unload_me(%v)\n", pconn_vhdl);
+#endif
+
+    if (GRAPH_SUCCESS !=
+	hwgraph_traverse(pconn_vhdl, PCIBA_EDGE_LBL_CFG, &c_vhdl))
+	return;
+
+    hwgraph_vertex_unref(c_vhdl);
+}
+
+/* ================================================================
+ *            standard unix entry points
+ */
+
+/*ARGSUSED */
+int
+pciba_open(dev_t *devp, int flag, int otyp, struct cred *crp)
+{
+
+#if DEBUG_PCIBA
+    printf("pciba_open(%V)\n", *devp);
+#endif
+    return 0;
+}
+
+/*ARGSUSED */
+int
+pciba_close(dev_t dev)
+{
+    devfs_handle_t         vhdl = dev_to_vhdl(dev);
+    pciba_soft_t            soft = pciba_soft_get(vhdl);
+
+#if DEBUG_PCIBA
+    printf("pciba_close(%V)\n", dev);
+#endif
+
+    /* if there is pending DMA for this device, hit the
+     * device over the head with a baseball bat and
+     * release the system memory resources.
+     */
+    if (soft && soft->comm->dmap) {
+	pciba_dma_t             next;
+	pciba_dma_t             dmap;
+
+	pciba_soft_lock(soft);
+	if (dmap = soft->comm->dmap) {
+	    soft->comm->dmap = 0;
+
+	    pciio_reset(soft->comm->conn);
+
+	    do {
+		if (!dmap->kaddr)
+		    break;
+		if (!dmap->paddr)
+		    break;
+		if (dmap->bytes < NBPP)
+		    break;
+		next = dmap->next;
+		kvpfree(dmap->kaddr, dmap->bytes / NBPP);
+		dmap->paddr = 0;
+		dmap->bytes = 0;
+		DEL(dmap);
+	    } while (dmap = next);
+	}
+	pciba_soft_unlock(soft);
+    }
+    return 0;
+}
+
+/* ARGSUSED */
+int
+pciba_read(dev_t dev, cred_t *crp)
+{
+#if DEBUG_PCIBA
+    printf("pciba_read(%V)\n", dev);
+#endif
+
+    return EINVAL;
+}
+
+/* ARGSUSED */
+int
+pciba_write(dev_t dev, cred_t *crp)
+{
+#if DEBUG_PCIBA
+    printf("pciba_write(%V)\n", dev);
+#endif
+
+    return EINVAL;
+}
+
+/*ARGSUSED */
+int
+pciba_ioctl(dev_t dev, int cmd, void *uarg, int mode, cred_t *crp, int *rvalp)
+{
+    devfs_handle_t          vhdl;
+    pciba_soft_t            soft;
+    pciio_space_t           space;
+    ioctl_arg_buffer_t      arg;
+    int                     psize;
+    int                     err = 0;
+
+#if ULI
+    char		    abi = get_current_abi();
+    pciio_intr_t            intr=0;
+    device_desc_t           desc;
+    cpuid_t                 intrcpu;
+    unsigned                lines;
+    struct uli             *uli = 0;
+#endif
+    unsigned                flags;
+    void                   *kaddr = 0;
+    iopaddr_t               paddr;
+    pciba_dma_h             dmah;
+    pciba_dma_t             dmap = 0;
+    pciio_dmamap_t          dmamap = 0;
+    size_t                  bytes;
+    int                     pages;
+    pciaddr_t               daddr;
+
+#if DEBUG_PCIBA
+    printf("pciba_ioctl(%V,0x%x)\n", dev, cmd);
+#endif
+
+    psize = (cmd >> 16) & IOCPARM_MASK;
+
+#if ULI
+    ASSERT(sizeof(struct uliargs) > 8);	/* prevent CFG access conflict */
+    ASSERT(sizeof(struct uliargs) <= IOCPARM_MASK);
+#endif
+
+    arg.ca = uarg;
+
+    if ((psize > 0) && (cmd & (IOC_OUT | IOC_IN))) {
+	if (psize > sizeof(arg))
+	    err = EINVAL;		/* "bad parameter size */
+	else {
+	    if (cmd & IOC_OUT)
+		bzero(arg.data, psize);
+	    if ((cmd & IOC_IN) &&
+		(copyin(uarg, arg.data, psize) < 0))
+		err = EFAULT;		/* "parameter copyin failed" */
+	}
+    }
+    vhdl = dev_to_vhdl(dev);
+    soft = pciba_soft_get(vhdl);
+    space = soft->space;
+
+    if (err == 0) {
+	err = EINVAL;			/* "invalid ioctl for this vertex" */
+	switch (space) {
+#if ULI
+	case PCIIO_SPACE_NONE:		/* the "intr" vertex */
+	    /* PCIIOCSETULI: set up user interrupts.
+	     */
+	    lines = cmd & 15;
+	    if (ABI_IS_64BIT(abi)) {
+		if (cmd != PCIIOCSETULI(lines)) {
+		    err = EINVAL;		/* "invalid ioctl for this vertex" */
+		    break;
+		}
+	    }
+	    else {
+		struct uliargs uliargs;
+
+		if (cmd != PCIIOCSETULI32(lines)) {
+		    err = EINVAL;		/* "invalid ioctl for this vertex" */
+		    break;
+		}
+		
+		uliargs32_to_uliargs(&arg.uli32, &uliargs);
+		arg.uli = uliargs;
+	    }
+	    desc = device_desc_dup(soft->comm->conn);
+	    device_desc_flags_set(desc, (device_desc_flags_get(desc) |
+					 D_INTR_NOTHREAD));
+	    device_desc_intr_swlevel_set(desc, INTR_SWLEVEL_NOTHREAD_DEFAULT);
+	    device_desc_intr_name_set(desc, "PCIBA");
+	    device_desc_default_set(soft->comm->conn, desc);
+
+	    /* When designating interrupts, the slot number
+	     * is taken from the connection point.
+	     * Bits 0..3 are used to select INTA..INTD; more
+	     * than one bit can be specified. These should
+	     * be constructed using PCIIO_INTR_LINE_[ABCD].
+	     */
+	    intr = pciio_intr_alloc
+		(soft->comm->conn, desc, lines, soft->vhdl);
+	    if (intr == 0) {
+		err = ENOMEM;		/* "insufficient resources" */
+		break;
+	    }
+	    intrcpu = cpuvertex_to_cpuid(pciio_intr_cpu_get(intr));
+
+	    if (err = new_uli(&arg.uli, &uli, intrcpu)) {
+		break;			/* "unable to set up ULI" */
+	    }
+	    atomic_inc(&pciba_prevent_unload);
+
+	    pciio_intr_connect(intr, pciba_intr, uli, (void *) 0);
+
+	    /* NOTE: don't set the teardown function
+	     * until the interrupt is connected.
+	     */
+	    uli->teardownarg1 = (__psint_t) intr;
+	    uli->teardown = pciba_clearuli;
+
+	    arg.uli.id = uli->index;
+
+	    if (!ABI_IS_64BIT(abi)) {
+		struct uliargs32 uliargs32;
+		uliargs_to_uliargs32(&arg.uli, &uliargs32);
+		arg.uli32 = uliargs32;
+	    }
+
+	    err = 0;
+	    break;
+#endif
+
+	case PCIBA_SPACE_UDMA:		/* the "dma" vertex */
+
+	    switch (cmd) {
+
+	    case PCIIOCDMAALLOC:
+		/* PCIIOCDMAALLOC: allocate a chunk of physical
+		 * memory and set it up for DMA. Return the
+		 * PCI address that gets to it.
+		 * NOTE: this allocates memory local to the
+		 * CPU doing the ioctl, not local to the
+		 * device that will be doing the DMA.
+		 */
+
+		if (!_CAP_ABLE(CAP_DEVICE_MGT)) {
+		    err = EPERM;
+		    break;
+		}
+		/* separate the halves of the incoming parameter */
+		flags = arg.ud >> 32;
+		bytes = arg.ud & 0xFFFFFFFF;
+
+#if DEBUG_PCIBA
+		printf("pciba: user wants 0x%x bytes of DMA, flags 0x%x\n",
+		       bytes, flags);
+#endif
+
+		/* round up the requested size to the next highest page */
+		pages = (bytes + NBPP - 1) / NBPP;
+
+		/* make sure the requested size is something reasonable */
+		if (pages > pci_user_dma_max_pages) {
+#if DEBUG_PCIBA
+		    printf("pciba: request for too much buffer space\n");
+#endif
+		    err = EINVAL;
+		    break;		/* "request for too much buffer space" */
+		}
+		/* "correct" number of bytes */
+		bytes = pages * NBPP;
+
+		/* allocate the space */
+		/* XXX- force to same node as the device? */
+		/* XXX- someday, we want to handle user buffers,
+		 *    and noncontiguous pages, but this will
+		 *      require either fancy mapping or handing
+		 *      a list of blocks back to the user. For
+		 *      now, just tell users to allocate a lot of
+		 *      individual single-pages and manage their
+		 *      scatter-gather manually.
+		 */
+		kaddr = kvpalloc(pages, VM_DIRECT | KM_NOSLEEP, 0);
+		if (kaddr == 0) {
+#if DEBUG_PCIBA
+		    printf("pciba: unable to get %d contiguous pages\n", pages);
+#endif
+		    err = EAGAIN;	/* "insufficient resources, try again later" */
+		    break;
+		}
+#if DEBUG_PCIBA
+		printf("pciba: kaddr is 0x%x\n", kaddr);
+#endif
+		paddr = kvtophys(kaddr);
+
+		daddr = pciio_dmatrans_addr
+		    (soft->comm->conn, 0, paddr, bytes, flags);
+		if (daddr == 0) {	/* "no direct path available" */
+#if DEBUG_PCIBA
+		    printf("pciba: dmatrans failed, trying dmamap\n");
+#endif
+		    dmamap = pciio_dmamap_alloc
+			(soft->comm->conn, 0, bytes, flags);
+		    if (dmamap == 0) {
+#if DEBUG_PCIBA
+			printf("pciba: unable to allocate dmamap\n");
+#endif
+			err = ENOMEM;
+			break;		/* "out of mapping resources" */
+		    }
+		    daddr = pciio_dmamap_addr
+			(dmamap, paddr, bytes);
+		    if (daddr == 0) {
+#if DEBUG_PCIBA
+			printf("pciba: dmamap_addr failed\n");
+#endif
+			err = EINVAL;
+			break;		/* "can't get there from here" */
+		    }
+		}
+#if DEBUG_PCIBA
+		printf("pciba: daddr is 0x%x\n", daddr);
+#endif
+		NEW(dmap);
+		if (!dmap) {
+		    err = ENOMEM;
+		    break;		/* "no memory available" */
+		}
+		dmap->bytes = bytes;
+		dmap->pages = pages;
+		dmap->paddr = paddr;
+		dmap->kaddr = kaddr;
+		dmap->map = dmamap;
+		dmap->daddr = daddr;
+		dmap->handle = 0;
+
+#if DEBUG_PCIBA
+		printf("pciba: dmap 0x%x contains va 0x%x bytes 0x%x pa 0x%x pages 0x%x daddr 0x%x\n",
+		       dmap, kaddr, bytes, paddr, pages, daddr);
+#endif
+
+		arg.ud = dmap->daddr;
+
+		err = 0;
+		break;
+
+	    case PCIIOCDMAFREE:
+		/* PCIIOCDMAFREE: Find the chunk of
+		 * User DMA memory, and release its
+		 * resources back to the system.
+		 */
+
+		if (!_CAP_ABLE(CAP_DEVICE_MGT)) {
+		    err = EPERM;	/* "you can't do that" */
+		    break;
+		}
+		if (soft->comm->dmap == NULL) {
+		    err = EINVAL;	/* "no User DMA to free" */
+		    break;
+		}
+		/* find the request. */
+		daddr = arg.ud;
+		err = EINVAL;		/* "block not found" */
+		pciba_soft_lock(soft);
+		for (dmah = &soft->comm->dmap; dmap = *dmah; dmah = &dmap->next) {
+		    if (dmap->daddr == daddr) {
+			if (dmap->handle != 0) {
+			    dmap = 0;	/* don't DEL this dmap! */
+			    err = EINVAL;	/* "please unmap first" */
+			    break;		/* break outa for loop. */
+			}
+			*dmah = dmap->next;
+
+			if (dmamap = dmap->map) {
+			    pciio_dmamap_free(dmamap);
+			    dmamap = 0;	/* don't free it twice! */
+			}
+			kvpfree(dmap->kaddr, dmap->bytes / NBPP);
+			DEL(dmap);
+			dmap = 0;	/* don't link this back into the list! */
+			err = 0;	/* "all done" */
+			break;		/* break outa for loop. */
+		    }
+		}
+		pciba_soft_unlock(soft);
+		break;		/* break outa case PCIIOCDMAFREE: */
+	    }
+	    break;		/* break outa case PCIBA_SPACE_UDMA: */
+
+	case PCIIO_SPACE_CFG:
+
+	    /* PCIIOCCFG{RD,WR}: read and/or write
+	     * PCI configuration space. If both,
+	     * the read happens first (this becomes
+	     * a swap operation, atomic with respect
+	     * to other updates through this path).
+	     *
+	     * Should be *last* IOCTl command checked,
+	     * so other patterns can nip useless codes
+	     * out of the space this decodes.
+	     */
+	    err = EINVAL;
+	    if ((psize > 0) || (psize <= 8) &&
+		(((cmd & 0xFF) + psize) <= 256) &&
+		(cmd & (IOC_IN | IOC_OUT))) {
+
+		uint64_t                rdata;
+		uint64_t                wdata;
+		int                     shft;
+
+		shft = 64 - (8 * psize);
+
+		wdata = arg.ud >> shft;
+
+		pciba_soft_lock(soft);
+
+		if (cmd & IOC_OUT)
+		    rdata = pciio_config_get(soft->comm->conn, cmd & 0xFFFF, psize);
+		if (cmd & IOC_IN)
+		    pciio_config_set(soft->comm->conn, cmd & 0xFFFF, psize, wdata);
+
+		pciba_soft_unlock(soft);
+
+		arg.ud = rdata << shft;
+		err = 0;
+		break;
+	    }
+	    break;
+	}
+    }
+    /* done: come here if all went OK.
+     */
+    if ((err == 0) &&
+	((cmd & IOC_OUT) && (psize > 0)) &&
+	copyout(arg.data, uarg, psize))
+	err = EFAULT;
+
+    /* This gets delayed until after the copyout so we
+     * do not free the dmap on a copyout error, or
+     * alternately end up with a dangling allocated
+     * buffer that the user never got back.
+     */
+    if ((err == 0) && dmap) {
+	pciba_soft_lock(soft);
+	dmap->next = soft->comm->dmap;
+	soft->comm->dmap = dmap;
+	pciba_soft_unlock(soft);
+    }
+    if (err) {
+	/* Things went badly. Clean up.
+	 */
+#if ULI
+	if (intr) {
+	    pciio_intr_disconnect(intr);
+	    pciio_intr_free(intr);
+	}
+	if (uli)
+	    free_uli(uli);
+#endif
+	if (dmap) {
+	    if (dmap->map && (dmap->map != dmamap))
+		pciio_dmamap_free(dmap->map);
+	    DEL(dmap);
+	}
+	if (dmamap)
+	    pciio_dmamap_free(dmamap);
+	if (kaddr)
+	    kvpfree(kaddr, pages);
+    }
+    return *rvalp = err;
+}
+
+/* ================================================================
+ *            mapping support
+ */
+
+/*ARGSUSED */
+int
+pciba_map(dev_t dev, vhandl_t *vt,
+	  off_t off, size_t len, uint32_t prot)
+{
+    devfs_handle_t          vhdl = dev_to_vhdl(dev);
+    pciba_soft_t            soft = pciba_soft_get(vhdl);
+    devfs_handle_t          conn = soft->comm->conn;
+    pciio_space_t           space = soft->space;
+    size_t                  pages = (len + NBPP - 1) / NBPP;
+    pciio_piomap_t          pciio_piomap = 0;
+    caddr_t                 kaddr;
+    pciba_map_t             map;
+    pciba_dma_t             dmap;
+
+#if DEBUG_PCIBA
+    printf("pciba_map(%V,vt=0x%x)\n", dev, vt);
+#endif
+
+    if (space == PCIBA_SPACE_UDMA) {
+	pciba_soft_lock(soft);
+
+	for (dmap = soft->comm->dmap; dmap != NULL; dmap = dmap->next) {
+	    if (off == dmap->daddr) {
+		if (pages != dmap->pages) {
+		    pciba_soft_unlock(soft);
+		    return EINVAL;	/* "size mismatch" */
+		}
+		v_mapphys(vt, dmap->kaddr, dmap->bytes);
+		dmap->handle = v_gethandle(vt);
+		pciba_soft_unlock(soft);
+#if DEBUG_PCIBA
+		printf("pciba: mapped dma at kaddr 0x%x via handle 0x%x\n",
+		       dmap->kaddr, dmap->handle);
+#endif
+		return 0;
+	    }
+	}
+	pciba_soft_unlock(soft);
+	return EINVAL;			/* "block not found" */
+    }
+    if (soft->iomem == PCIIO_SPACE_NONE)
+	return EINVAL;			/* "mmap not supported" */
+
+    kaddr = (caddr_t) pciio_pio_addr
+	(conn, 0, space, off, len, &pciio_piomap, soft->flags | PCIIO_FIXED );
+
+#if DEBUG_PCIBA
+    printf("pciba: mapped %R[0x%x..0x%x] via map 0x%x to kaddr 0x%x\n",
+	   space, space_desc, off, off + len - 1, pciio_piomap, kaddr);
+#endif
+
+    if (kaddr == NULL)
+	return EINVAL;			/* "you can't get there from here" */
+
+    NEW(map);
+    if (map == NULL) {
+	if (pciio_piomap)
+	    pciio_piomap_free(pciio_piomap);
+	return ENOMEM;			/* "unable to get memory resources */
+    }
+#ifdef LATER
+    map->uthread = curuthread;
+#endif
+    map->handle = v_gethandle(vt);
+    map->uvaddr = v_getaddr(vt);
+    map->map = pciio_piomap;
+    map->space = soft->iomem;
+    map->base = soft->base + off;
+    map->size = len;
+    pciba_map_push(soft->comm->bus, map);
+
+    /* Inform the system of the correct
+     * kvaddr corresponding to the thing
+     * that is being mapped.
+     */
+    v_mapphys(vt, kaddr, len);
+
+    return 0;
+}
+
+/*ARGSUSED */
+int
+pciba_unmap(dev_t dev, vhandl_t *vt)
+{
+    devfs_handle_t         vhdl = dev_to_vhdl(dev);
+    pciba_soft_t            soft = pciba_soft_get(vhdl);
+    pciba_bus_t             bus = soft->comm->bus;
+    pciba_map_t             map;
+    __psunsigned_t          handle = v_gethandle(vt);
+
+#if DEBUG_PCIBA
+    printf("pciba_unmap(%V,vt=%x)\n", dev, vt);
+#endif
+
+    /* If this is a userDMA buffer,
+     * make a note that it has been unmapped
+     * so it can be released.
+     */
+    if (soft->comm->dmap) {
+	pciba_dma_t             dmap;
+
+	pciba_soft_lock(soft);
+	for (dmap = soft->comm->dmap; dmap != NULL; dmap = dmap->next)
+	    if (handle == dmap->handle) {
+		dmap->handle = 0;
+		pciba_soft_unlock(soft);
+#if DEBUG_PCIBA
+		printf("pciba: unmapped dma at kaddr 0x%x via handle 0x%x\n",
+		       dmap->kaddr, handle);
+#endif
+		return 0;		/* found userPCI */
+	    }
+	pciba_soft_unlock(soft);
+    }
+    map = pciba_map_pop_hdl(bus, handle);
+    if (map == NULL)
+	return EINVAL;			/* no match */
+
+    if (map->map)
+	pciio_piomap_free(map->map);
+    DEL(map);
+
+    return (0);				/* all done OK */
+}
+
+#if ULI
+void
+pciba_clearuli(struct uli *uli)
+{
+    pciio_intr_t            intr = (pciio_intr_t) uli->teardownarg1;
+
+#if DEBUG_PCIBA
+    printf("pciba_clearuli(0x%x)\n", uli);
+#endif
+
+    pciio_intr_disconnect(intr);
+    pciio_intr_free(intr);
+    atomic_dec(&pciba_prevent_unload);
+}
+
+void
+pciba_intr(intr_arg_t arg)
+{
+    struct uli             *uli = (struct uli *) arg;
+    int                     ulinum = uli->index;
+
+    extern void frs_handle_uli(void);
+
+    if (ulinum >= 0 && ulinum < MAX_ULIS) {
+	    uli_callup(ulinum);
+
+	    if (private.p_frs_flags)
+		    frs_handle_uli();
+    }
+}
+#endif
+#endif /* LATER - undef as we implement each routine */
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/pcibr.c linux/arch/ia64/sn/io/pcibr.c
--- v2.4.3/linux/arch/ia64/sn/io/pcibr.c	Tue Mar  6 19:44:35 2001
+++ linux/arch/ia64/sn/io/pcibr.c	Thu Apr 12 12:16:35 2001
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/config.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
@@ -22,7 +23,6 @@
 #include <asm/sn/invent.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
-#include <asm/sn/cmn_err.h>
 #include <asm/sn/xtalk/xwidget.h>
 #include <asm/sn/pci/bridge.h>
 #include <asm/sn/pci/pciio.h>
@@ -41,6 +41,14 @@
 #include <asm/sn/sn1/hubio_next.h>
 #endif
 
+#ifdef __ia64
+#define rmallocmap atemapalloc
+#define rmfreemap atemapfree
+#define rmfree atefree
+#define rmalloc atealloc
+#endif
+
+#undef PCIBR_ATE_DEBUG
 #if defined(BRINGUP)
 #if 0
 #define DEBUG 1	 /* To avoid lots of bad printk() formats leave off */
@@ -54,6 +62,24 @@
 #define	LOCAL		static
 #endif
 
+/*
+ * Macros related to the Lucent USS 302/312 usb timeout workaround.  It
+ * appears that if the lucent part can get into a retry loop if it sees a
+ * DAC on the bus during a pio read retry.  The loop is broken after about
+ * 1ms, so we need to set up bridges holding this part to allow at least
+ * 1ms for pio.
+ */
+
+#define USS302_TIMEOUT_WAR
+
+#ifdef USS302_TIMEOUT_WAR
+#include <asm/sn/io.h>
+#define LUCENT_USBHC_VENDOR_ID_NUM	0x11c1
+#define LUCENT_USBHC302_DEVICE_ID_NUM	0x5801
+#define LUCENT_USBHC312_DEVICE_ID_NUM	0x5802
+#define USS302_BRIDGE_TIMEOUT_HLD	4
+#endif
+
 #define PCIBR_LLP_CONTROL_WAR
 #if defined (PCIBR_LLP_CONTROL_WAR)
 int                     pcibr_llp_control_war_cnt;
@@ -69,6 +95,7 @@
 
 int                     pcibr_devflag = D_MP;
 
+#ifdef LATER
 #define F(s,n)		{ 1l<<(s),-(s), n }
 
 struct reg_desc         bridge_int_status_desc[] =
@@ -246,6 +273,7 @@
     {0}
 };
 #endif
+#endif	/* LATER */
 
 /* kbrick widgetnum-to-bus layout */
 int p_busnum[MAX_PORT_NUM] = {                  /* widget#      */
@@ -275,8 +303,8 @@
  * CPU to a particular IO device are synched before the start of the next
  * set of PIO operations to the same device.
  */
-#define pcibr_lock(pcibr_soft)		io_splock(pcibr_soft->bs_lock)
-#define pcibr_unlock(pcibr_soft, s)	io_spunlock(pcibr_soft->bs_lock,s)
+#define pcibr_lock(pcibr_soft)		io_splock(&pcibr_soft->bs_lock)
+#define pcibr_unlock(pcibr_soft,s)	io_spunlock(&pcibr_soft->bs_lock,s)
 
 #if PCIBR_SOFT_LIST
 typedef struct pcibr_list_s *pcibr_list_p;
@@ -302,6 +330,31 @@
 extern int      hub_device_flags_set(devfs_handle_t       widget_dev,
                                      hub_widget_flags_t flags);
 #endif
+extern pciio_dmamap_t get_free_pciio_dmamap(devfs_handle_t);
+
+/*
+ * This is the file operation table for the pcibr driver.
+ * As each of the functions are implemented, put the 
+ * appropriate function name below.
+ */
+struct file_operations pcibr_fops = {
+        owner:  THIS_MODULE,
+        llseek: NULL,
+        read: NULL,
+        write: NULL,
+        readdir: NULL,
+        poll: NULL,
+        ioctl: NULL,
+        mmap: NULL,
+        open: NULL,
+        flush: NULL,
+        release: NULL,
+        fsync: NULL,
+        fasync: NULL,
+        lock: NULL,
+        readv: NULL,
+        writev: NULL
+};
 
 extern devfs_handle_t hwgraph_root;
 extern graph_error_t hwgraph_vertex_unref(devfs_handle_t vhdl);
@@ -317,7 +370,7 @@
 extern struct map *rmallocmap(uint64_t mapsiz);
 extern void rmfreemap(struct map *mp);
 extern int compare_and_swap_ptr(void **location, void *old_ptr, void *new_ptr);
-extern void cmn_err_tag(int seqnumber, register int level, char *fmt, ...);
+extern int io_path_map_widget(devfs_handle_t vertex);
 
 
 
@@ -363,17 +416,13 @@
 
 void                    pcibr_freeblock_sub(iopaddr_t *, iopaddr_t *, iopaddr_t, size_t);
 
-#ifndef BRINGUP
 LOCAL int               pcibr_init_ext_ate_ram(bridge_t *);
-#endif
 LOCAL int               pcibr_ate_alloc(pcibr_soft_t, int);
 LOCAL void              pcibr_ate_free(pcibr_soft_t, int, int);
 
 LOCAL pcibr_info_t      pcibr_info_get(devfs_handle_t);
 LOCAL pcibr_info_t      pcibr_device_info_new(pcibr_soft_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t);
 LOCAL void		pcibr_device_info_free(devfs_handle_t, pciio_slot_t);
-LOCAL int		pcibr_device_attach(devfs_handle_t,pciio_slot_t);
-LOCAL int		pcibr_device_detach(devfs_handle_t,pciio_slot_t);
 LOCAL iopaddr_t         pcibr_addr_pci_to_xio(devfs_handle_t, pciio_slot_t, pciio_space_t, iopaddr_t, size_t, unsigned);
 
 pcibr_piomap_t          pcibr_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned);
@@ -411,7 +460,7 @@
 
 devfs_handle_t            pcibr_intr_cpu_get(pcibr_intr_t);
 void                    pcibr_xintr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);
-void                    pcibr_intr_list_func(intr_arg_t);
+void                    pcibr_intr_func(intr_arg_t);
 
 LOCAL void              print_bridge_errcmd(uint32_t, char *);
 
@@ -450,21 +499,32 @@
 void			pcibr_hints_intr_bits(devfs_handle_t, pcibr_intr_bits_f *);
 void                    pcibr_set_rrb_callback(devfs_handle_t, rrb_alloc_funct_t);
 void                    pcibr_hints_handsoff(devfs_handle_t);
-void                    pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, uint64_t);
+void                    pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, ulong);
 
-LOCAL int		pcibr_slot_reset(devfs_handle_t,pciio_slot_t);
 LOCAL int		pcibr_slot_info_init(devfs_handle_t,pciio_slot_t);
 LOCAL int		pcibr_slot_info_free(devfs_handle_t,pciio_slot_t);
+
+#ifdef LATER
+LOCAL int	        pcibr_slot_info_return(pcibr_soft_t, pciio_slot_t,
+                                               pcibr_slot_info_resp_t);
+LOCAL void       	pcibr_slot_func_info_return(pcibr_info_h, int,
+                                                    pcibr_slot_func_info_resp_t);
+#endif	/* LATER */
+
 LOCAL int		pcibr_slot_addr_space_init(devfs_handle_t,pciio_slot_t);
 LOCAL int		pcibr_slot_device_init(devfs_handle_t, pciio_slot_t);
 LOCAL int		pcibr_slot_guest_info_init(devfs_handle_t,pciio_slot_t);
 LOCAL int		pcibr_slot_initial_rrb_alloc(devfs_handle_t,pciio_slot_t);
-LOCAL int		pcibr_slot_call_device_attach(devfs_handle_t,pciio_slot_t);
-LOCAL int		pcibr_slot_call_device_detach(devfs_handle_t,pciio_slot_t);
+LOCAL int		pcibr_slot_call_device_attach(devfs_handle_t,
+						      pciio_slot_t, int);
+LOCAL int		pcibr_slot_call_device_detach(devfs_handle_t,
+						      pciio_slot_t, int);
 
-int			pcibr_slot_powerup(devfs_handle_t,pciio_slot_t);
-int			pcibr_slot_shutdown(devfs_handle_t,pciio_slot_t);
-int			pcibr_slot_inquiry(devfs_handle_t,pciio_slot_t);		
+LOCAL int               pcibr_slot_detach(devfs_handle_t, pciio_slot_t, int);
+LOCAL int 		pcibr_is_slot_sys_critical(devfs_handle_t, pciio_slot_t);
+#ifdef LATER
+LOCAL int		pcibr_slot_query(devfs_handle_t, pcibr_slot_info_req_t);
+#endif
 
 /* =====================================================================
  *    RRB management
@@ -754,7 +814,7 @@
     int                     final_vchan0;
     int                     final_vchan1;
     int                     avail_rrbs;
-    unsigned                s;
+    unsigned long           s;
     int                     error;
 
     /*
@@ -930,7 +990,7 @@
     pciio_info_t            pciio_info;
     pciio_slot_t            pciio_slot;
     pcibr_soft_t            pcibr_soft;
-    unsigned                s;
+    unsigned long           s;
     int                     error = -1;
 
     if ((pciio_info = pciio_info_get(pconn_vhdl)) &&
@@ -978,11 +1038,7 @@
 		     int dev_3_rrbs, int virt3, int dev_4_rrbs, int virt4)
 {
     devfs_handle_t            pcibr_vhdl;
-#ifdef colin
-    pcibr_soft_t            pcibr_soft;
-#else
-    pcibr_soft_t	pcibr_soft = NULL;
-#endif
+    pcibr_soft_t            pcibr_soft = NULL;
     bridge_t               *bridge = NULL;
 
     uint32_t              rrb_setting = 0;
@@ -991,7 +1047,7 @@
     int                     dev_rrbs[4];
     int                     virt[4];
     int                     i, j;
-    unsigned                s;
+    unsigned long           s;
 
     if (GRAPH_SUCCESS ==
 	hwgraph_traverse(vhdl, EDGE_LBL_PCI, &pcibr_vhdl)) {
@@ -1089,7 +1145,7 @@
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
     pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);
     bridge_t               *bridge = pcibr_soft->bs_base;
-    unsigned                s;
+    unsigned long           s;
     reg_p                   rrbp;
     unsigned                rrbm;
     int                     i;
@@ -1141,7 +1197,7 @@
     bridgereg_t             badd32;
     bridgereg_t             badd64;
     bridgereg_t             fix;
-    unsigned                s;
+    unsigned long           s;
     bridgereg_t             xmask;
 
     xmask = mask;
@@ -1203,29 +1259,16 @@
     /* Generic macro flags
      */
     if (flags & PCIIO_DMA_DATA) {
-#ifdef colin
-	new = new
-	    & ~BRIDGE_DEV_BARRIER	/* barrier off */
-	    | BRIDGE_DEV_PREF;		/* prefetch on */
-#else
 	new = (new
             & ~BRIDGE_DEV_BARRIER)      /* barrier off */
             | BRIDGE_DEV_PREF;          /* prefetch on */
-#endif
 
     }
     if (flags & PCIIO_DMA_CMD) {
-#ifdef colin
-	new = new
-	    & ~BRIDGE_DEV_PREF		/* prefetch off */
-	    & ~BRIDGE_DEV_WRGA_BITS	/* write gather off */
-	    | BRIDGE_DEV_BARRIER;	/* barrier on */
-#else
         new = ((new
             & ~BRIDGE_DEV_PREF)         /* prefetch off */
             & ~BRIDGE_DEV_WRGA_BITS)    /* write gather off */
             | BRIDGE_DEV_BARRIER;       /* barrier on */
-#endif
     }
     /* Generic detail flags
      */
@@ -1297,13 +1340,8 @@
 	     * but the alternative is not allowing
 	     * the new stream at all.
 	     */
-#ifdef colin
-	    if (fix = bad & (BRIDGE_DEV_PRECISE |
-			     BRIDGE_DEV_BARRIER)) {
-#else
             if ( (fix = bad & (BRIDGE_DEV_PRECISE |
                              BRIDGE_DEV_BARRIER)) ){
-#endif
 		bad &= ~fix;
 		/* don't change these bits if
 		 * they are already set in "old"
@@ -1317,13 +1355,8 @@
 	     * but the alternative is not allowing
 	     * the new stream at all.
 	     */
-#ifdef colin
-	    if (fix = bad & (BRIDGE_DEV_WRGA_BITS |
-			     BRIDGE_DEV_PREF)) {
-#else
 	    if ( (fix = bad & (BRIDGE_DEV_WRGA_BITS |
-			     BRIDGE_DEV_PREF)) ){
-#endif
+			     BRIDGE_DEV_PREF)) ) {
 		bad &= ~fix;
 		/* don't change these bits if
 		 * we wanted to turn them on.
@@ -1379,7 +1412,7 @@
 		     bridgereg_t mask)
 {
     pcibr_soft_slot_t       slotp;
-    unsigned                s;
+    unsigned long           s;
 
     slotp = &pcibr_soft->bs_slot[slot];
 
@@ -1403,7 +1436,7 @@
               pciio_slot_t slot)
 {
     bridge_t               *bridge;
-    unsigned                s;
+    unsigned long          s;
     volatile uint32_t     wrf;
     s = pcibr_lock(pcibr_soft);
     bridge = pcibr_soft->bs_base;
@@ -1429,14 +1462,14 @@
 {
     int                     rv;
     bridgereg_t             old_enable, new_enable;
+    int badaddr_val(volatile void *, int, volatile void *);
+
 
     old_enable = bridge->b_int_enable;
     new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT;
 
     bridge->b_int_enable = new_enable;
 
-#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
-#if defined(BRINGUP)
 	/*
 	 * The xbridge doesn't clear b_err_int_view unless
 	 * multi-err is cleared...
@@ -1445,8 +1478,6 @@
 	    if (bridge->b_err_int_view & BRIDGE_ISR_PCI_MST_TIMEOUT) {
 		bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR;
 	    }
-#endif	/* BRINGUP */
-#endif	/* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */
 
     if (bridge->b_int_status & BRIDGE_IRR_PCI_GRP) {
 	bridge->b_int_rst_stat = BRIDGE_IRR_PCI_GRP_CLR;
@@ -1454,8 +1485,6 @@
     }
     rv = badaddr_val((void *) cfg, 4, valp);
 
-#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
-#if defined(BRINGUP)
 	/*
 	 * The xbridge doesn't set master timeout in b_int_status
 	 * here.  Fortunately it's in error_interrupt_view.
@@ -1465,8 +1494,6 @@
 		bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR;
 		rv = 1;		/* unoccupied slot */
 	    }
-#endif	/* BRINGUP */
-#endif /* CONFIG_SGI_IP35 */
 
     bridge->b_int_enable = old_enable;
     bridge->b_wid_tflush;		/* wait until Bridge PIO complete */
@@ -1514,10 +1541,6 @@
 int
 pcibr_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp)
 {
-#ifndef CONFIG_IA64_SGI_IO
-    if (!_CAP_CRABLE((uint64_t)credp, (uint64_t)CAP_DEVICE_MGT))
-	return EPERM;
-#endif
     return 0;
 }
 
@@ -1630,42 +1653,10 @@
 
     return slot;
 }
+
 /*==========================================================================
  *	BRIDGE PCI SLOT RELATED IOCTLs
  */
-/*
- * pcibr_slot_powerup
- *	Software initialize the pci slot.
- */
-int
-pcibr_slot_powerup(devfs_handle_t pcibr_vhdl,pciio_slot_t slot)
-{
-    /* Check for the valid slot */
-    if (!PCIBR_VALID_SLOT(slot))
-	return(EINVAL);
-
-    if (pcibr_device_attach(pcibr_vhdl,slot))
-	return(EINVAL);
-
-    return(0);
-}
-/*
- * pcibr_slot_shutdown
- *	Software shutdown the pci slot
- */
-int
-pcibr_slot_shutdown(devfs_handle_t pcibr_vhdl,pciio_slot_t slot)
-{
-    /* Check for valid slot */
-    if (!PCIBR_VALID_SLOT(slot))
-	return(EINVAL);
-
-    if (pcibr_device_detach(pcibr_vhdl,slot))
-	return(EINVAL);
-
-    return(0);
-}
-
 char *pci_space_name[] = {"NONE", 
 			  "ROM",
 			  "IO",
@@ -1683,177 +1674,163 @@
 			  "",
 			  "BAD"};
 
+
+#ifdef LATER
+
 void
-pcibr_slot_func_info_print(pcibr_info_h pcibr_infoh, int func, int verbose)
+pcibr_slot_func_info_return(pcibr_info_h pcibr_infoh,
+                            int func,
+                            pcibr_slot_func_info_resp_t funcp)
 {
-    pcibr_info_t	pcibr_info = pcibr_infoh[func];
-    char		name[MAXDEVNAME];
-    int			win;
-    
-    if (!pcibr_info)
-	return;
+    pcibr_info_t                 pcibr_info = pcibr_infoh[func];
+    int                          win;
 
+    funcp->resp_f_status = 0;
+
+    if (!pcibr_info) {
+        return;
+    }
+
+    funcp->resp_f_status |= FUNC_IS_VALID;
 #ifdef SUPPORT_PRINTING_V_FORMAT
-    sprintf(name, "%v", pcibr_info->f_vertex);
-#endif
-    if (!verbose) {
-	printk("\tSlot Name : %s\n",name);
-    } else {
-	printk("\tPER-SLOT FUNCTION INFO\n");
-#ifdef SUPPORT_PRINTING_V_FORMAT
-	sprintf(name, "%v", pcibr_info->f_vertex);
+    sprintf(funcp->resp_f_slot_name, "%v", pcibr_info->f_vertex);
+#else
+    sprintf(funcp->resp_f_slot_name, "%x", pcibr_info->f_vertex);
 #endif
-	printk("\tSlot Name : %s\n",name);
-	printk("\tPCI Bus : %d ",pcibr_info->f_bus);
-	printk("Slot : %d ", pcibr_info->f_slot);
-	printk("Function : %d\n", pcibr_info->f_func);
+
+    if(is_sys_critical_vertex(pcibr_info->f_vertex)) {
+        funcp->resp_f_status |= FUNC_IS_SYS_CRITICAL;
+    }
+
+    funcp->resp_f_bus = pcibr_info->f_bus;
+    funcp->resp_f_slot = pcibr_info->f_slot;
+    funcp->resp_f_func = pcibr_info->f_func;
 #ifdef SUPPORT_PRINTING_V_FORMAT
-	sprintf(name, "%v", pcibr_info->f_master);
+    sprintf(funcp->resp_f_master_name, "%v", pcibr_info->f_master);
+#else
+    sprintf(funcp->resp_f_master_name, "%x", pcibr_info->f_master);
 #endif
-	printk("\tBus provider : %s\n",name);
-	printk("\tProvider Fns : 0x%p ", pcibr_info->f_pops);
-	printk("Error Handler : 0x%p Arg 0x%p\n", 
-		pcibr_info->f_efunc,pcibr_info->f_einfo);
+    funcp->resp_f_pops = pcibr_info->f_pops;
+    funcp->resp_f_efunc = pcibr_info->f_efunc;
+    funcp->resp_f_einfo = pcibr_info->f_einfo;
+
+    funcp->resp_f_vendor = pcibr_info->f_vendor;
+    funcp->resp_f_device = pcibr_info->f_device;
+
+    for(win = 0 ; win < 6 ; win++) {
+        funcp->resp_f_window[win].resp_w_base =
+                                  pcibr_info->f_window[win].w_base;
+        funcp->resp_f_window[win].resp_w_size =
+                                  pcibr_info->f_window[win].w_size;
+        sprintf(funcp->resp_f_window[win].resp_w_space,
+                "%s",
+                pci_space_name[pcibr_info->f_window[win].w_space]);
     }
-    printk("\tVendorId : 0x%x " , pcibr_info->f_vendor);
-    printk("DeviceId : 0x%x\n", pcibr_info->f_device);
 
-    printk("\n\tBase Register Info\n");
-    printk("\t\tReg#\tBase\t\tSize\t\tSpace\n");
-    for(win = 0 ; win < 6 ; win++) 
-	printk("\t\t%d\t0x%lx\t%s0x%lx\t%s%s\n",
-		win,
-		pcibr_info->f_window[win].w_base,
-		pcibr_info->f_window[win].w_base >= 0x100000 ? "": "\t",
-		pcibr_info->f_window[win].w_size,
-		pcibr_info->f_window[win].w_size >= 0x100000 ? "": "\t",
-		pci_space_name[pcibr_info->f_window[win].w_space]);
-
-    printk("\t\t7\t0x%x\t%s0x%x\t%sROM\n", 
-	    pcibr_info->f_rbase,
-	    pcibr_info->f_rbase > 0x100000 ? "" : "\t",
-	    pcibr_info->f_rsize,
-	    pcibr_info->f_rsize > 0x100000 ? "" : "\t");
+    funcp->resp_f_rbase = pcibr_info->f_rbase;
+    funcp->resp_f_rsize = pcibr_info->f_rsize;
 
-    printk("\n\tInterrupt Bit Map\n");
-    printk("\t\tPCI Int#\tBridge Pin#\n");
-    for (win = 0 ; win < 4; win++)
-	printk("\t\tINT%c\t\t%d\n",win+'A',pcibr_info->f_ibit[win]);
-    printk("\n");
-}
+    for (win = 0 ; win < 4; win++) {
+        funcp->resp_f_ibit[win] = pcibr_info->f_ibit[win];
+    }
 
+    funcp->resp_f_att_det_error = pcibr_info->f_att_det_error;
 
-void
-pcibr_slot_info_print(pcibr_soft_t 	pcibr_soft, 
-		      pciio_slot_t 	slot, 
-		      int	   	verbose)
-{
-    pcibr_soft_slot_t	pss;
-    char		slot_conn_name[MAXDEVNAME];
-    int			func;
-    bridge_t		*bridge = pcibr_soft->bs_base;
-    bridgereg_t		b_resp;
-    reg_p		b_respp;
-    int			dev;
-    bridgereg_t		b_int_device;
-    bridgereg_t		b_int_host;
-    bridgereg_t		b_int_enable;
-    int			pin = 0;
-    int			int_bits = 0;
+}
+
+int
+pcibr_slot_info_return(pcibr_soft_t             pcibr_soft,
+                       pciio_slot_t             slot,
+                       pcibr_slot_info_resp_t   respp)
+{
+    pcibr_soft_slot_t            pss;
+    int                          func;
+    bridge_t                    *bridge = pcibr_soft->bs_base;
+    reg_p                        b_respp;
+    pcibr_slot_info_resp_t       slotp;
+    pcibr_slot_func_info_resp_t  funcp;
+
+    slotp = kmem_zalloc(sizeof(*slotp), KM_SLEEP);
+    if (slotp == NULL) {
+        return(ENOMEM);
+    }
 
     pss = &pcibr_soft->bs_slot[slot];
     
     printk("\nPCI INFRASTRUCTURAL INFO FOR SLOT %d\n\n", slot);
 
-    if (verbose) {
-	printk("\tHost Present ? %s ", pss->has_host ? "yes" : "no");
-	printk("\tHost Slot : %d\n",pss->host_slot);
+    slotp->resp_has_host = pss->has_host;
+    slotp->resp_host_slot = pss->host_slot;
 #ifdef SUPPORT_PRINTING_V_FORMAT
-	sprintf(slot_conn_name, "%v", pss->slot_conn);
+    sprintf(slotp->resp_slot_conn_name, "%v", pss->slot_conn);
+#else
+    sprintf(slotp->resp_slot_conn_name, "%x", pss->slot_conn);
 #endif
-	printk("\tSlot Conn : %s\n",slot_conn_name);	
-	printk("\t#Functions : %d\n",pss->bss_ninfo);
+    slotp->resp_slot_status = pss->slot_status;
+    slotp->resp_l1_bus_num = io_path_map_widget(pcibr_soft->bs_vhdl);
+
+    if (is_sys_critical_vertex(pss->slot_conn)) {
+        slotp->resp_slot_status |= SLOT_IS_SYS_CRITICAL;
     }
-    for (func = 0; func < pss->bss_ninfo; func++)
-	pcibr_slot_func_info_print(pss->bss_infos,func, verbose);
-    printk("\tDevio[Space:%s,Base:0x%lx,Shadow:0x%x]\n",
-	    pci_space_name[pss->bss_devio.bssd_space],
-	    pss->bss_devio.bssd_base,
-	    pss->bss_device);
-
-    if (verbose) {
-	printk("\tUsage counts : pmu %d d32 %d d64 %d\n",
-		pss->bss_pmu_uctr,pss->bss_d32_uctr,pss->bss_d64_uctr);
-    
-	printk("\tDirect Trans Info : d64_base 0x%x d64_flags 0x%x"
-		"d32_base 0x%x d32_flags 0x%x\n",
-		(unsigned int)pss->bss_d64_base, pss->bss_d64_flags,
-		(unsigned int)pss->bss_d32_base, pss->bss_d32_flags);
-    
-	printk("\tExt ATEs active ? %s", 
-		pss->bss_ext_ates_active ? "yes" : "no");
-	printk(" Command register : 0x%p ", pss->bss_cmd_pointer);
-	printk(" Shadow command val : 0x%x\n", pss->bss_cmd_shadow);
+
+    slotp->resp_bss_ninfo = pss->bss_ninfo;
+
+    for (func = 0; func < pss->bss_ninfo; func++) {
+        funcp = &(slotp->resp_func[func]);
+        pcibr_slot_func_info_return(pss->bss_infos, func, funcp);
     }
 
-    printk("\tSoft RRB Info[Valid %d+%d, Reserved %d]\n",
-	    pcibr_soft->bs_rrb_valid[slot],
-	    pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],
-	    pcibr_soft->bs_rrb_res[slot]);
+    sprintf(slotp->resp_bss_devio_bssd_space, "%s",
+            pci_space_name[pss->bss_devio.bssd_space]);
+    slotp->resp_bss_devio_bssd_base = pss->bss_devio.bssd_base;
+    slotp->resp_bss_device = pss->bss_device;
 
+    slotp->resp_bss_pmu_uctr = pss->bss_pmu_uctr;
+    slotp->resp_bss_d32_uctr = pss->bss_d32_uctr;
+    slotp->resp_bss_d64_uctr = pss->bss_d64_uctr;
 
-    if (slot & 1)
-	b_respp = &bridge->b_odd_resp;
-    else
-	b_respp = &bridge->b_even_resp;
+    slotp->resp_bss_d64_base = pss->bss_d64_base;
+    slotp->resp_bss_d64_flags = pss->bss_d64_flags;
+    slotp->resp_bss_d32_base = pss->bss_d32_base;
+    slotp->resp_bss_d32_flags = pss->bss_d32_flags;
 
-    b_resp = *b_respp;
+    slotp->resp_bss_ext_ates_active = atomic_read(&pss->bss_ext_ates_active);
 
-    printk("\n\tBridge RRB Info\n");
-    printk("\t\tRRB#\tVirtual\n");
-    for (dev = 0; dev < 8; dev++) {
-	if ((b_resp & BRIDGE_RRB_EN) &&
-	    (b_resp & BRIDGE_RRB_PDEV) == (slot >> 1))
-	    printk( "\t\t%d\t%s\n", 
-		    dev,
-		    (b_resp & BRIDGE_RRB_VDEV) ? "yes" : "no");
-	b_resp >>= 4;
-	    
-    }
-    b_int_device = bridge->b_int_device;
-    b_int_enable = bridge->b_int_enable;
+    slotp->resp_bss_cmd_pointer = pss->bss_cmd_pointer;
+    slotp->resp_bss_cmd_shadow = pss->bss_cmd_shadow;
 
-    printk("\n\tBridge Interrupt Info\n"
-	    "\t\tInt_device 0x%x\n\t\tInt_enable 0x%x "
-	    "\n\t\tEnabled pin#s for this slot: ",
-	    b_int_device,
-	    b_int_enable);
+    slotp->resp_bs_rrb_valid = pcibr_soft->bs_rrb_valid[slot];
+    slotp->resp_bs_rrb_valid_v = pcibr_soft->bs_rrb_valid[slot +
+                                                      PCIBR_RRB_SLOT_VIRTUAL];
+    slotp->resp_bs_rrb_res = pcibr_soft->bs_rrb_res[slot];
 
-    while (b_int_device) {
-	if (((b_int_device & 7) == slot) &&
-	    (b_int_enable & (1 << pin))) {
-	    int_bits |= (1 << pin);
-	    printk("%d ", pin); 
-	}
-	pin++;
-	b_int_device >>= 3;
+    if (slot & 1) {
+        b_respp = &bridge->b_odd_resp;
+    } else {
+        b_respp = &bridge->b_even_resp;
     }
 
-    if (!int_bits)
-	printk("NONE ");
+    slotp->resp_b_resp = *b_respp;
 
-    b_int_host = bridge->b_int_addr[slot].addr;
+    slotp->resp_b_int_device = bridge->b_int_device;
+    slotp->resp_b_int_enable = bridge->b_int_enable;
+    slotp->resp_b_int_host = bridge->b_int_addr[slot].addr;
 
-    printk("\n\t\tInt_host_addr 0x%x\n",
-	    b_int_host);
-    
+    if (COPYOUT(slotp, respp, sizeof(*respp))) {
+        return(EFAULT);
+    }
+
+    kmem_free(slotp, sizeof(*slotp));
+
+    return(0);
 }
 
-int verbose = 0;
 /*
- * pcibr_slot_inquiry
- *	Print information about the pci slot maintained by the infrastructure.
- *	Current information displayed
+ * pcibr_slot_query
+ *	Return information about the PCI slot maintained by the infrastructure.
+ *	Information is requested in the request structure.
+ *
+ *      Information returned in the response structure:
  *		Slot hwgraph name
  *		Vendor/Device info
  *		Base register info
@@ -1861,7 +1838,6 @@
  *		Devio register
  *		Software RRB info
  *		RRB register info
- *	In verbose mode following additional info is displayed
  *		Host/Gues info
  *		PCI Bus #,slot #, function #
  *		Slot provider hwgraph name
@@ -1872,28 +1848,76 @@
  *		External SSRAM workaround info
  */
 int
-pcibr_slot_inquiry(devfs_handle_t pcibr_vhdl, pciio_slot_t slot)
+pcibr_slot_query(devfs_handle_t pcibr_vhdl, pcibr_slot_info_req_t reqp)
 {
-    pcibr_soft_t	pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    pcibr_soft_t            pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    pciio_slot_t            slot = reqp->req_slot;
+    pciio_slot_t            tmp_slot;
+    pcibr_slot_info_resp_t  respp = (pcibr_slot_info_resp_t) reqp->req_respp;
+    int                     size = reqp->req_size;
+    int                     error;
 
     /* Make sure that we are dealing with a bridge device vertex */
-    if (!pcibr_soft)
-	return(EINVAL);
+    if (!pcibr_soft) {
+        return(EINVAL);
+    }
 
-    /* Make sure that we have a valid pci slot number or PCIIO_SLOT_NONE */
-    if ((!PCIBR_VALID_SLOT(slot)) && (slot != PCIIO_SLOT_NONE))
-	return(EINVAL);
+    /* Make sure that we have a valid PCI slot number or PCIIO_SLOT_NONE */
+    if ((!PCIBR_VALID_SLOT(slot)) && (slot != PCIIO_SLOT_NONE)) {
+        return(EINVAL);
+    }
 
-    /* Print information for the requested pci slot */
+#ifdef LATER
+    /* Do not allow a query of a slot in a shoehorn */
+    if(nic_vertex_info_match(pcibr_soft->bs_conn, XTALK_PCI_PART_NUM)) {
+       return(EPERM);
+    }
+#endif
+
+    /* Return information for the requested PCI slot */
     if (slot != PCIIO_SLOT_NONE) {
-	pcibr_slot_info_print(pcibr_soft,slot,verbose);
-	return(0);
+        if (size < sizeof(*respp)) {
+            return(EINVAL);
+        }
+
+        /* Acquire read access to the slot */
+        mrlock(pcibr_soft->bs_slot[slot].slot_lock, MR_ACCESS, PZERO);
+
+        error = pcibr_slot_info_return(pcibr_soft, slot, respp);
+
+        /* Release the slot lock */
+        mrunlock(pcibr_soft->bs_slot[slot].slot_lock);
+
+        return(error);
     }
-    /* Print information for all the slots */
-    for (slot = 0; slot < 8; slot++)
-	pcibr_slot_info_print(pcibr_soft, slot,verbose);
-    return(0);
+
+    /* Return information for all the slots */
+    for (tmp_slot = 0; tmp_slot < 8; tmp_slot++) {
+
+        if (size < sizeof(*respp)) {
+            return(EINVAL);
+        }
+
+        /* Acquire read access to the slot */
+        mrlock(pcibr_soft->bs_slot[tmp_slot].slot_lock, MR_ACCESS, PZERO);
+
+        error = pcibr_slot_info_return(pcibr_soft, tmp_slot, respp);
+
+        /* Release the slot lock */
+        mrunlock(pcibr_soft->bs_slot[tmp_slot].slot_lock);
+
+        if (error) {
+            return(error);
+        }
+
+        ++respp;
+        size -= sizeof(*respp);
+    }
+
+    return(error);
 }
+#endif	/* LATER */
+
 
 /*ARGSUSED */
 int
@@ -1905,7 +1929,7 @@
 	    int *rvalp)
 {
     devfs_handle_t            pcibr_vhdl = hwgraph_connectpt_get((devfs_handle_t)dev);
-#ifdef colin
+#ifdef LATER
     pcibr_soft_t            pcibr_soft = pcibr_soft_get(pcibr_vhdl);
 #endif
     int                     error = 0;
@@ -1913,7 +1937,7 @@
     hwgraph_vertex_unref(pcibr_vhdl);
 
     switch (cmd) {
-#ifdef colin
+#ifdef LATER
     case GIOCSETBW:
 	{
 	    grio_ioctl_info_t       info;
@@ -1969,7 +1993,6 @@
 		pcibr_priority_bits_set(pcibr_soft, slot, PCI_PRIO_LOW);
 	    break;
 	}
-#endif /* colin */
 
     case PCIBR_SLOT_POWERUP:
 	{
@@ -1985,31 +2008,33 @@
 	    break;
 	}
     case PCIBR_SLOT_SHUTDOWN:
-	{
-	    pciio_slot_t	slot;
-
 	    if (!cap_able(CAP_DEVICE_MGT)) {
 		error = EPERM;
 		break;
 	    }
 
 	    slot = (pciio_slot_t)(uint64_t)arg;
-	    error = pcibr_slot_shutdown(pcibr_vhdl,slot);
+	    error = pcibr_slot_powerup(pcibr_vhdl,slot);
 	    break;
 	}
-    case PCIBR_SLOT_INQUIRY:
+    case PCIBR_SLOT_QUERY:
 	{
-	    pciio_slot_t	slot;
+	    struct pcibr_slot_info_req_s        req;
 
 	    if (!cap_able(CAP_DEVICE_MGT)) {
 		error = EPERM;
 		break;
 	    }
 
-	    slot = (pciio_slot_t)(uint64_t)arg;
-	    error = pcibr_slot_inquiry(pcibr_vhdl,slot);
+            if (COPYIN(arg, &req, sizeof(req))) {
+                error = EFAULT;
+                break;
+            }
+
+            error = pcibr_slot_query(pcibr_vhdl, &req);
 	    break;
 	}
+#endif	/* LATER */
     default:
 	break;
 
@@ -2055,7 +2080,6 @@
 	*free_basep = last + 1;		/* keep upper chunk */
 }
 
-#ifdef IRIX
 /* Convert from ssram_bits in control register to number of SSRAM entries */
 #define ATE_NUM_ENTRIES(n) _ate_info[n]
 
@@ -2070,14 +2094,12 @@
 
 #define ATE_NUM_SIZES (sizeof(_ate_info) / sizeof(int))
 #define ATE_PROBE_VALUE 0x0123456789abcdefULL
-#endif	/* IRIX */
 
 /*
  * Determine the size of this bridge's external mapping SSRAM, and set
  * the control register appropriately to reflect this size, and initialize
  * the external SSRAM.
  */
-#ifndef BRINGUP
 LOCAL int
 pcibr_init_ext_ate_ram(bridge_t *bridge)
 {
@@ -2087,9 +2109,6 @@
     bridgereg_t             old_enable, new_enable;
     int                     s;
 
-    if (is_xbridge(bridge))
-	return 0;
-
     /* Probe SSRAM to determine its size. */
     old_enable = bridge->b_int_enable;
     new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT;
@@ -2116,11 +2135,9 @@
      */
 
     s = splhi();
-#ifdef colin
     bridge->b_wid_control = (bridge->b_wid_control
 	& ~BRIDGE_CTRL_SSRAM_SIZE_MASK)
 	| BRIDGE_CTRL_SSRAM_SIZE(largest_working_size);
-#endif
     bridge->b_wid_control;		/* inval addr bug war */
     splx(s);
 
@@ -2139,7 +2156,6 @@
 
     return (num_entries);
 }
-#endif	/* !BRINGUP */
 
 /*
  * Allocate "count" contiguous Bridge Address Translation Entries
@@ -2155,6 +2171,7 @@
     int                     index = 0;
 
     index = (int) rmalloc(pcibr_soft->bs_int_ate_map, (size_t) count);
+/* printk("Colin: pcibr_ate_alloc - index %d count %d \n", index, count); */
 
     if (!index && pcibr_soft->bs_ext_ate_map)
 	index = (int) rmalloc(pcibr_soft->bs_ext_ate_map, (size_t) count);
@@ -2174,6 +2191,8 @@
     /* note the "+1" since rmalloc handles 1..n but
      * we start counting ATEs at zero.
      */
+/* printk("Colin: pcibr_ate_free - index %d count %d\n", index, count); */
+
     rmfree((index < pcibr_soft->bs_int_ate_size)
 	   ? pcibr_soft->bs_int_ate_map
 	   : pcibr_soft->bs_ext_ate_map,
@@ -2233,8 +2252,6 @@
 	/*
 	 * Record the info in the sparse func info space.
 	 */
-printk("pcibr_device_info_new: slot= %d  func= %d  bss_ninfo= %d  pcibr_info= 0x%p\n", slot, func, pcibr_soft->bs_slot[slot].bss_ninfo, pcibr_info);
-
 	if (func < pcibr_soft->bs_slot[slot].bss_ninfo)
 	    pcibr_soft->bs_slot[slot].bss_infos[func] = pcibr_info;
     }
@@ -2281,7 +2298,7 @@
     slotp->bss_d32_flags = 0;
 
     /* Clear out shadow info necessary for the external SSRAM workaround */
-    slotp->bss_ext_ates_active = 0;
+    slotp->bss_ext_ates_active = ATOMIC_INIT(0);
     slotp->bss_cmd_pointer = 0;
     slotp->bss_cmd_shadow = 0;
 
@@ -2336,55 +2353,10 @@
 	   pcibr_soft->bs_spinfo.pci_mem_last);
 
 /*
- * pcibr_slot_reset
- *	Reset the pci device in the particular slot .
- */
-int
-pcibr_slot_reset(devfs_handle_t pcibr_vhdl,pciio_slot_t slot)
-{
-	pcibr_soft_t		pcibr_soft = pcibr_soft_get(pcibr_vhdl);
-	bridge_t		*bridge;
-	bridgereg_t		ctrlreg,tmp;
-	volatile bridgereg_t	*wrb_flush;
-
-	if (!PCIBR_VALID_SLOT(slot))
-		return(1);
-
-	if (!pcibr_soft)
-		return(1);
-
-	/* Enable the DMA operations from this device of the xtalk widget
-	 * (PCI host bridge in this case).
-	 */
-	xtalk_widgetdev_enable(pcibr_soft->bs_conn, slot);
-	/* Set the reset slot bit in the bridge's wid control register
-	 * to reset the pci slot 
-	 */
-	bridge = pcibr_soft->bs_base;
-	/* Read the bridge widget control and clear out the reset pin
-	 * bit for the corresponding slot. 
-	 */
-	tmp = ctrlreg = bridge->b_wid_control;
-	tmp &= ~BRIDGE_CTRL_RST_PIN(slot); 
-	bridge->b_wid_control = tmp;
-	tmp = bridge->b_wid_control;
-	/* Restore the old control register back.
-	 * NOTE : pci card gets reset when the reset pin bit
-	 * changes from 0 (set above) to 1 (going to be set now).
-	 */
-	bridge->b_wid_control = ctrlreg;
-
-	/* Flush the write buffers if any !! */
-	wrb_flush = &(bridge->b_wr_req_buf[slot].reg);
-	while (*wrb_flush);
-
-	return(0);
-}
-/*
  * pcibr_slot_info_init
  *	Probe for this slot and see if it is populated.
- *	If it is populated initialize the generic pci infrastructural
- * 	information associated with this particular pci device.
+ *	If it is populated initialize the generic PCI infrastructural
+ * 	information associated with this particular PCI device.
  */
 int
 pcibr_slot_info_init(devfs_handle_t 	pcibr_vhdl,
@@ -2401,6 +2373,9 @@
     pciio_vendor_id_t       vendor;
     pciio_device_id_t       device;
     unsigned                htype;
+#if !defined(CONFIG_IA64_SGI_SN1)
+    int			    nbars;
+#endif
     cfg_p                   wptr;
     int                     win;
     pciio_space_t           space;
@@ -2416,40 +2391,41 @@
     /* Get the basic software information required to proceed */
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
     if (!pcibr_soft)
-	return(1);
+	return(EINVAL);
 
     bridge = pcibr_soft->bs_base;
     if (!PCIBR_VALID_SLOT(slot))
-	return(1);
-
-    slotp = &pcibr_soft->bs_slot[slot];
-
-    /* Load the current values of allocated pci address spaces */
-    PCI_ADDR_SPACE_LIMITS_LOAD();
+	return(EINVAL);
 
-    /* If we have a host slot (eg:- IOC3 has 2 pci slots and the initialization
+    /* If we have a host slot (eg:- IOC3 has 2 PCI slots and the initialization
      * is done by the host slot then we are done.
      */
-    if (pcibr_soft->bs_slot[slot].has_host)
-	return(0);
+    if (pcibr_soft->bs_slot[slot].has_host) {
+	return(0);    
+    }
+
+    /* Check for a slot with any system critical functions */
+    if (pcibr_is_slot_sys_critical(pcibr_vhdl, slot))
+        return(EPERM);
+
+    /* Load the current values of allocated PCI address spaces */
+    PCI_ADDR_SPACE_LIMITS_LOAD();
     
     /* Try to read the device-id/vendor-id from the config space */
     cfgw = bridge->b_type0_cfg_dev[slot].l;
 
-#ifdef BRINGUP
-    if (slot < 3  || slot == 7) 
-	return (0);
-    else
-#endif /* BRINGUP */
-    if (pcibr_probe_slot(bridge, cfgw, &idword))
-	return(0);
+    if (pcibr_probe_slot(bridge, cfgw, &idword)) 
+	return(ENODEV);
+
+    slotp = &pcibr_soft->bs_slot[slot];
+    slotp->slot_status |= SLOT_POWER_UP;
 
     vendor = 0xFFFF & idword;
     /* If the vendor id is not valid then the slot is not populated
      * and we are done.
      */
-    if (vendor == 0xFFFF)
-	return(0);			/* next slot */
+    if (vendor == 0xFFFF) 
+	return(ENODEV);			
     
     device = 0xFFFF & (idword >> 16);
     htype = do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1);
@@ -2503,7 +2479,13 @@
 	if (htype != 0x00) {
 	    PRINT_WARNING("%s pcibr: pci slot %d func %d has strange header type 0x%x\n",
 		    pcibr_soft->bs_name, slot, func, htype);
+#if defined(CONFIG_IA64_SGI_SN1)
 	    continue;
+#else
+	    nbars = 2;
+	} else {
+	    nbars = PCI_CFG_BASE_ADDRS;
+#endif
 	}
 #if DEBUG && ATTACH_DEBUG
 	PRINT_NOTICE( 
@@ -2516,13 +2498,17 @@
 	conn_vhdl = pciio_device_info_register(pcibr_vhdl, &pcibr_info->f_c);
 	if (func == 0)
 	    slotp->slot_conn = conn_vhdl;
-	
+
 	cmd_reg = cfgw[PCI_CFG_COMMAND / 4];
 	
 	wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4;
 
-
-	for (win = 0; win < PCI_CFG_BASE_ADDRS; ++win) {
+#if defined(CONFIG_IA64_SGI_SN1)
+	for (win = 0; win < PCI_CFG_BASE_ADDRS; ++win)
+#else
+	for (win = 0; win < nbars; ++win)
+#endif
+	{
 	    iopaddr_t               base, mask, code;
 	    size_t                  size;
 
@@ -2573,9 +2559,9 @@
 	    base = wptr[((win*4)^4)/4];
 #else
 	    base = wptr[win];
-#endif /* LITTLE_ENDIAN */
+#endif
 
-	    if (base & 1) {
+	    if (base & PCI_BA_IO_SPACE) {
 		/* BASE is in I/O space. */
 		space = PCIIO_SPACE_IO;
 		mask = -4;
@@ -2590,7 +2576,7 @@
 		/* BASE is in MEM space. */
 		space = PCIIO_SPACE_MEM;
 		mask = -16;
-		code = base & 15;
+		code = base & PCI_BA_MEM_LOCATION;	/* extract BAR type */
 		base = base & mask;
 		if (base == 0) {
 		    ;		/* not assigned */
@@ -2697,37 +2683,30 @@
 	}				/* next win */
     }				/* next func */
 
-    /* Store back the values for allocated pci address spaces */
+    /* Store back the values for allocated PCI address spaces */
     PCI_ADDR_SPACE_LIMITS_STORE();
     return(0);
 }					
 
 /*
  * pcibr_slot_info_free
- *	Remove all the pci infrastructural information associated
- * 	with a particular pci device.
+ *	Remove all the PCI infrastructural information associated
+ * 	with a particular PCI device.
  */
 int
-pcibr_slot_info_free(devfs_handle_t 	pcibr_vhdl,
-		     pciio_slot_t	slot)
+pcibr_slot_info_free(devfs_handle_t pcibr_vhdl,
+                     pciio_slot_t slot)
 {
     pcibr_soft_t	pcibr_soft;
     pcibr_info_h	pcibr_infoh;
     int			nfunc;
-#if defined(PCI_HOTSWAP_DEBUG)
-    cfg_p		cfgw;
-    bridge_t		*bridge;
-    int			win;
-    cfg_p		wptr;
-#endif /* PCI_HOTSWAP_DEBUG */
-
-    
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
-#if defined(PCI_HOTSWAP_DEBUG)
+#if !defined(CONFIG_IA64_SGI_SN1)
     /* Clean out all the base registers */
     bridge = pcibr_soft->bs_base;
     cfgw = bridge->b_type0_cfg_dev[slot].l;
@@ -2739,7 +2718,7 @@
 #else
 	wptr[win] = 0;
 #endif  /* LITTLE_ENDIAN */
-#endif /* PCI_HOTSWAP_DEBUG */
+#endif	/* !CONFIG_IA64_SGI_SN1 */
 
     nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
 
@@ -2750,13 +2729,12 @@
     pcibr_soft->bs_slot[slot].bss_ninfo = 0;
 
     return(0);
-    
-
 }
+
 int as_debug = 0;
 /*
  * pcibr_slot_addr_space_init
- *	Reserve chunks of pci address space as required by 
+ *	Reserve chunks of PCI address space as required by 
  * 	the base registers in the card.
  */
 int
@@ -2772,38 +2750,40 @@
     iopaddr_t		pci_hi_fb, pci_hi_fl;
     size_t              align;
     iopaddr_t           mask;
+    int		    	nbars;
     int		       	nfunc;
     int			func;
     int			win;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
     bridge = pcibr_soft->bs_base;
 
-    /* Get the current values for the allocated pci address spaces */
+    /* Get the current values for the allocated PCI address spaces */
     PCI_ADDR_SPACE_LIMITS_LOAD();
 
     if (as_debug)
-#ifdef colin
+#ifdef LATER
     PCI_ADDR_SPACE_LIMITS_PRINT();
 #endif
     /* allocate address space,
      * for windows that have not been
      * previously assigned.
      */
-
-    if (pcibr_soft->bs_slot[slot].has_host)
+    if (pcibr_soft->bs_slot[slot].has_host) {
 	return(0);
+    }
 
     nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
     if (nfunc < 1)
-	return(0);
+	return(EINVAL);
 
     pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;
     if (!pcibr_infoh)
-	return(0);
+	return(EINVAL);
 
     /*
      * Try to make the DevIO windows not
@@ -2842,7 +2822,16 @@
 	cfgw = bridge->b_type0_cfg_dev[slot].f[func].l;
 	wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4;
 
-	for (win = 0; win < PCI_CFG_BASE_ADDRS; ++win) {
+#if defined(CONFIG_IA64_SGI_SN1)
+	nbars = PCI_CFG_BASE_ADDRS;
+#else
+	if ((do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1) & 0x7f) != 0)
+	    nbars = 2;
+	else
+	    nbars = PCI_CFG_BASE_ADDRS;
+#endif
+
+	for (win = 0; win < nbars; ++win) {
 
 	    space = pcibr_info->f_window[win].w_space;
 	    base = pcibr_info->f_window[win].w_base;
@@ -2908,7 +2897,9 @@
 	    pcibr_info->f_window[win].w_base = base;
 #ifdef LITTLE_ENDIAN
 	    wptr[((win*4)^4)/4] = base;
+#if DEBUG && PCI_DEBUG
 		printk("Setting base address 0x%p base 0x%x\n", &(wptr[((win*4)^4)/4]), base);
+#endif
 #else
 	    wptr[win] = base;
 #endif  /* LITTLE_ENDIAN */
@@ -2976,7 +2967,22 @@
 	 * be sure are set.
 	 */
 	pci_cfg_cmd_reg_add |= PCI_CMD_IO_SPACE;
-	pci_cfg_cmd_reg_add |= PCI_CMD_MEM_SPACE;
+
+	/*
+	 * The Adaptec 1160 FC Controller WAR #767995:
+	 * The part incorrectly ignores the upper 32 bits of a 64 bit
+	 * address when decoding references to it's registers so to
+	 * keep it from responding to a bus cycle that it shouldn't
+	 * we only use I/O space to get at it's registers.  Don't
+	 * enable memory space accesses on that PCI device.
+	 */
+	#define FCADP_VENDID 0x9004 /* Adaptec Vendor ID from fcadp.h */
+	#define FCADP_DEVID 0x1160  /* Adaptec 1160 Device ID from fcadp.h */
+
+	if ((pcibr_info->f_vendor != FCADP_VENDID) ||
+	    (pcibr_info->f_device != FCADP_DEVID))
+	    pci_cfg_cmd_reg_add |= PCI_CMD_MEM_SPACE;
+
 	pci_cfg_cmd_reg_add |= PCI_CMD_BUS_MASTER;
 
 	pci_cfg_cmd_reg_p = cfgw + PCI_CFG_COMMAND / 4;
@@ -2991,28 +2997,30 @@
 	
     }				/* next func */
 
-    /* Now that we have allocated new chunks of pci address spaces to this
+    /* Now that we have allocated new chunks of PCI address spaces to this
      * card we need to update the bookkeeping values which indicate
-     * the current pci address space allocations.
+     * the current PCI address space allocations.
      */
     PCI_ADDR_SPACE_LIMITS_STORE();
     return(0);
 }
+
 /*
  * pcibr_slot_device_init
- * 	Setup the device register in the bridge for this pci slot.
+ * 	Setup the device register in the bridge for this PCI slot.
  */
 int
-pcibr_slot_device_init(devfs_handle_t 	pcibr_vhdl,
-		       pciio_slot_t    	slot)
+pcibr_slot_device_init(devfs_handle_t pcibr_vhdl,
+		       pciio_slot_t slot)
 {
-    pcibr_soft_t	pcibr_soft;
+    pcibr_soft_t	 pcibr_soft;
     bridge_t		*bridge;
-    bridgereg_t		devreg;
+    bridgereg_t		 devreg;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
     bridge = pcibr_soft->bs_base;
 
@@ -3036,13 +3044,13 @@
 #if DEBUG && PCI_DEBUG
     printk("pcibr: PCI space allocation done.\n");
 #endif
-	
+
     return(0);
 }
 
 /*
  * pcibr_slot_guest_info_init
- *	Setup the host/guest relations for a pci slot.
+ *	Setup the host/guest relations for a PCI slot.
  */
 int
 pcibr_slot_guest_info_init(devfs_handle_t pcibr_vhdl,
@@ -3056,7 +3064,7 @@
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
 
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
     slotp = &pcibr_soft->bs_slot[slot];
 
@@ -3103,17 +3111,17 @@
 
     return(0);
 }
+
 /*
  * pcibr_slot_initial_rrb_alloc
  *	Allocate a default number of rrbs for this slot on 
- * 	the two channels. This is dictated by the rrb allocation
+ * 	the two channels.  This is dictated by the rrb allocation
  * 	strategy routine defined per platform.
  */
 
 int
-pcibr_slot_initial_rrb_alloc(devfs_handle_t 	pcibr_vhdl,
-			     pciio_slot_t	slot)
-
+pcibr_slot_initial_rrb_alloc(devfs_handle_t pcibr_vhdl,
+			     pciio_slot_t slot)
 {
     pcibr_soft_t	pcibr_soft;
     pcibr_info_h	pcibr_infoh;
@@ -3123,16 +3131,17 @@
     int			r;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
     bridge = pcibr_soft->bs_base;
 
-
     /* How may RRBs are on this slot?
      */
     c0 = do_pcibr_rrb_count_valid(bridge, slot);
     c1 = do_pcibr_rrb_count_valid(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL);
+
 #if PCIBR_RRB_DEBUG
     printk("pcibr_attach: slot %d started with %d+%d\n", slot, c0, c1);
 #endif
@@ -3149,7 +3158,7 @@
 	    do_pcibr_rrb_free(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL, c1);
 	pcibr_soft->bs_rrb_valid[slot] = 0x1000;
 	pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = 0x1000;
-	return(0);
+	return(ENODEV);
     }
 
     pcibr_soft->bs_rrb_avail[slot & 1] -= c0 + c1;
@@ -3173,17 +3182,19 @@
 	    pcibr_soft->bs_rrb_res[slot]);
     printk("\n");
 #endif
+
     return(0);
 }
 
 /*
  * pcibr_slot_call_device_attach
- *	This calls the associated driver attach routine for the pci
+ *	This calls the associated driver attach routine for the PCI
  * 	card in this slot.
  */
 int
-pcibr_slot_call_device_attach(devfs_handle_t	pcibr_vhdl,
-			      pciio_slot_t	slot)
+pcibr_slot_call_device_attach(devfs_handle_t pcibr_vhdl,
+			      pciio_slot_t slot,
+			      int          drv_flags)
 {
     pcibr_soft_t	pcibr_soft;
     pcibr_info_h	pcibr_infoh;
@@ -3192,14 +3203,19 @@
     int			func;
     devfs_handle_t	xconn_vhdl,conn_vhdl;
     int			nfunc;
+    int                 error_func;
+    int                 error_slot = 0;
+    int                 error = ENODEV;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
 
-    if (pcibr_soft->bs_slot[slot].has_host)
-        return(0);
+    if (pcibr_soft->bs_slot[slot].has_host) {
+        return(EPERM);
+    }
     
     xconn_vhdl = pcibr_soft->bs_conn;
     aa = async_attach_get_info(xconn_vhdl);
@@ -3207,8 +3223,6 @@
     nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
     pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;
 
-    printk("\npcibr_slot_call_device_attach: link 0x%p pci bus 0x%p slot %d\n", xconn_vhdl, pcibr_vhdl, slot);
-
     for (func = 0; func < nfunc; ++func) {
 
 	pcibr_info = pcibr_infoh[func];
@@ -3221,51 +3235,77 @@
 
 	conn_vhdl = pcibr_info->f_vertex;
 
-	/* If the pci device has been disabled in the prom,
+	/* If the PCI device has been disabled in the prom,
 	 * do not set it up for driver attach. NOTE: usrpci
 	 * and pciba will not "see" this connection point!
 	 */
 	if (device_admin_info_get(conn_vhdl, ADMIN_LBL_DISABLED)) {
 #ifdef SUPPORT_PRINTING_V_FORMAT
-	    PRINT_WARNING( "pcibr_slot_call_device_attach: %v disabled\n", 
+	    PRINT_WARNING("pcibr_slot_call_device_attach: %v disabled\n", 
 		    conn_vhdl);
 #endif
 	    continue;
 	}
+#ifdef LATER
+	/*
+	 * Activate if and when we support cdl.
+	 */
 	if (aa)
 	    async_attach_add_info(conn_vhdl, aa);
-	pciio_device_attach(conn_vhdl);
-    }				/* next func */
+#endif	/* LATER */
 
-    printk("\npcibr_slot_call_device_attach: DONE\n");
+	error_func = pciio_device_attach(conn_vhdl, drv_flags);
 
-    return(0);
+        pcibr_info->f_att_det_error = error_func;
+
+	if (error_func)
+	    error_slot = error_func;
+
+        error = error_slot;
+
+    }				/* next func */
+
+    if (error) {
+	if ((error != ENODEV) && (error != EUNATCH))
+	    pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_INCMPLT;
+    } else {
+        pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT;
+    }
+        
+    return(error);
 }
+
 /*
  * pcibr_slot_call_device_detach
- *	This calls the associated driver detach routine for the pci
+ *	This calls the associated driver detach routine for the PCI
  * 	card in this slot.
  */
 int
-pcibr_slot_call_device_detach(devfs_handle_t	pcibr_vhdl,
-			      pciio_slot_t	slot)
+pcibr_slot_call_device_detach(devfs_handle_t pcibr_vhdl,
+			      pciio_slot_t slot,
+			      int          drv_flags)
 {
     pcibr_soft_t	pcibr_soft;
     pcibr_info_h	pcibr_infoh;
     pcibr_info_t	pcibr_info;
     int			func;
-    devfs_handle_t	conn_vhdl;
+    devfs_handle_t	conn_vhdl = GRAPH_VERTEX_NONE;
     int			nfunc;
-    int			ndetach = 1;
+    int                 error_func;
+    int                 error_slot = 0;
+    int                 error = ENODEV;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
-    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
 
+    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
+	return(EINVAL);
 
     if (pcibr_soft->bs_slot[slot].has_host)
-        return(0);
-    
+        return(EPERM);
+
+    /* Make sure that we do not detach a system critical function vertex */
+    if(pcibr_is_slot_sys_critical(pcibr_vhdl, slot))
+        return(EPERM);
 
     nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
     pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;
@@ -3281,94 +3321,120 @@
 	    continue;
 
 	conn_vhdl = pcibr_info->f_vertex;
-	
-	/* Make sure that we do not detach a system critical device
-	 * vertex.
-	 */
-	if (is_sys_critical_vertex(conn_vhdl)) {
-#ifdef SUPPORT_PRINTING_V_FORMAT
-	    PRINT_WARNING( "%v is a system critical device vertex\n",
-		    conn_vhdl);
-#endif
-	    continue;
-	}
-	
-	ndetach = 0;
-	pciio_device_detach(conn_vhdl);
+
+	error_func = pciio_device_detach(conn_vhdl, drv_flags);
+
+        pcibr_info->f_att_det_error = error_func;
+
+	if (error_func)
+	    error_slot = error_func;
+
+	error = error_slot;
+
     }				/* next func */
 
+    pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
 
-    return(ndetach);
+    if (error) {
+	if ((error != ENODEV) && (error != EUNATCH))
+            pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_INCMPLT;
+    } else {
+        if (conn_vhdl != GRAPH_VERTEX_NONE) 
+            pcibr_device_unregister(conn_vhdl);
+        pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT;
+    }
+        
+    return(error);
 }
 
 /*
- * pcibr_device_attach
+ * pcibr_slot_detach
  *	This is a place holder routine to keep track of all the
- *	slot-specific initialization that needs to be done.
- *	This is usually called when we want to initialize a new
- * 	pci card on the bus.
+ *	slot-specific freeing that needs to be done.
  */
 int
-pcibr_device_attach(devfs_handle_t 	pcibr_vhdl,
-		    pciio_slot_t	slot)
+pcibr_slot_detach(devfs_handle_t pcibr_vhdl,
+		  pciio_slot_t slot,
+		  int          drv_flags)
 {
-    return (
-	    /* Reset the slot */
-	    pcibr_slot_reset(pcibr_vhdl,slot)			||
-	    /* FInd out what is out there */
-	    pcibr_slot_info_init(pcibr_vhdl,slot)		||
-
-	    /* Set up the address space for this slot in the pci land */
-	    pcibr_slot_addr_space_init(pcibr_vhdl,slot) 	||
-
-	    /* Setup the device register */
-	    pcibr_slot_device_init(pcibr_vhdl, slot)		||
-
-	    /* Setup host/guest relations */
-	    pcibr_slot_guest_info_init(pcibr_vhdl,slot)		||
-
-	    /* Initial RRB management */
-	    pcibr_slot_initial_rrb_alloc(pcibr_vhdl,slot)	||
-
-	    /* Call the device attach */
-	    pcibr_slot_call_device_attach(pcibr_vhdl,slot)
-	    );
+    int		  error;
+    
+    /* Call the device detach function */
+    error = (pcibr_slot_call_device_detach(pcibr_vhdl, slot, drv_flags));
+    return (error);
 
 }
+
 /*
- * pcibr_device_detach
- *	This is a place holder routine to keep track of all the
- *	slot-specific freeing that needs to be done.
+ * pcibr_is_slot_sys_critical
+ *      Check slot for any functions that are system critical.
+ *      Return 1 if any are system critical or 0 otherwise.
+ *
+ *      This function will always return 0 when called by 
+ *      pcibr_attach() because the system critical vertices 
+ *      have not yet been set in the hwgraph.
  */
 int
-pcibr_device_detach(devfs_handle_t 	pcibr_vhdl,
-		    pciio_slot_t	slot)
+pcibr_is_slot_sys_critical(devfs_handle_t pcibr_vhdl,
+                      pciio_slot_t slot)
 {
-    
-    /* Call the device detach */
-    return (pcibr_slot_call_device_detach(pcibr_vhdl,slot));
+    pcibr_soft_t        pcibr_soft;
+    pcibr_info_h        pcibr_infoh;
+    pcibr_info_t        pcibr_info;
+    devfs_handle_t        conn_vhdl = GRAPH_VERTEX_NONE;
+    int                 nfunc;
+    int                 func;
+
+    pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
+        return(0);
+
+    nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
+    pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;
+
+    for (func = 0; func < nfunc; ++func) {
+
+        pcibr_info = pcibr_infoh[func];
+        if (!pcibr_info)
+            continue;
+
+        if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE)
+            continue;
+
+        conn_vhdl = pcibr_info->f_vertex;
+        if (is_sys_critical_vertex(conn_vhdl)) { 
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+            PRINT_WARNING("%v is a system critical device vertex\n", conn_vhdl);
+#else
+            PRINT_WARNING("%p is a system critical device vertex\n", conn_vhdl);
+#endif
+            return(1); 
+        }
+
+    }
 
+    return(0);
 }
+
 /*
  * pcibr_device_unregister
- *	This frees up any hardware resources reserved for this pci device
- * 	and removes any pci infrastructural information setup for it.
- *	This is usually used at the time of shutting down of the pci card.
+ *	This frees up any hardware resources reserved for this PCI device
+ * 	and removes any PCI infrastructural information setup for it.
+ *	This is usually used at the time of shutting down of the PCI card.
  */
-void
+int
 pcibr_device_unregister(devfs_handle_t pconn_vhdl)
 {
-    pciio_info_t	pciio_info;
-    devfs_handle_t	pcibr_vhdl;
-    pciio_slot_t	slot;
-    pcibr_soft_t	pcibr_soft;
+    pciio_info_t	 pciio_info;
+    devfs_handle_t	 pcibr_vhdl;
+    pciio_slot_t	 slot;
+    pcibr_soft_t	 pcibr_soft;
     bridge_t		*bridge;
+    int			 error_call;
+    int			 error = 0;
 
     pciio_info = pciio_info_get(pconn_vhdl);
 
-    /* Detach the pciba name space */
-    pciio_device_detach(pconn_vhdl);
-
     pcibr_vhdl = pciio_info_master_get(pciio_info);
     slot = pciio_info_slot_get(pciio_info);
 
@@ -3382,19 +3448,31 @@
     pcibr_rrb_flush(pconn_vhdl);
 
     /* Free the rrbs allocated to this slot */
-    do_pcibr_rrb_free(bridge, slot, 
-		      pcibr_soft->bs_rrb_valid[slot] +
-		      pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL]);
+    error_call = do_pcibr_rrb_free(bridge, slot, 
+		                   pcibr_soft->bs_rrb_valid[slot] +
+		                   pcibr_soft->bs_rrb_valid[slot + 
+                                   PCIBR_RRB_SLOT_VIRTUAL]);
 
+    if (error_call)
+        error = ERANGE;
 
     pcibr_soft->bs_rrb_valid[slot] = 0;
     pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = 0;
     pcibr_soft->bs_rrb_res[slot] = 0;
 
     /* Flush the write buffers !! */
-    (void)pcibr_wrb_flush(pconn_vhdl);
+    error_call = pcibr_wrb_flush(pconn_vhdl);
+
+    if (error_call)
+        error = error_call;
+
     /* Clear the information specific to the slot */
-    (void)pcibr_slot_info_free(pcibr_vhdl, slot);
+    error_call = pcibr_slot_info_free(pcibr_vhdl, slot);
+
+    if (error_call)
+        error = error_call;
+
+    return(error);
     
 }
 
@@ -3467,6 +3545,7 @@
 	return (rv == GRAPH_SUCCESS);
 }
 
+
 /*
  *    pcibr_attach: called every time the crosstalk
  *      infrastructure is asked to initialize a widget
@@ -3502,11 +3581,15 @@
     iopaddr_t               pci_hi_fb, pci_hi_fl;
 
     int                     spl_level;
+#ifdef LATER
     char		    *nicinfo = (char *)0;
+#endif
 
 #if PCI_FBBE
     int                     fast_back_to_back_enable;
 #endif
+    l1sc_t		    *scp;
+    nasid_t		    nasid;
 
     async_attach_t          aa = NULL;
 
@@ -3542,8 +3625,6 @@
 	NeedXbridgeSwap = 1;
 #endif
 
-	printk("pcibr_attach: Called with vertex 0x%p, b_wid_stat 0x%x, gio 0x%x\n",xconn_vhdl, bridge->b_wid_stat, BRIDGE_STAT_PCI_GIO_N);
-
     /*
      * Create the vertex for the PCI bus, which we
      * will also use to hold the pcibr_soft and
@@ -3558,8 +3639,14 @@
     rc = hwgraph_path_add(xconn_vhdl, EDGE_LBL_PCI, &pcibr_vhdl);
     ASSERT(rc == GRAPH_SUCCESS);
 
-    rc = hwgraph_char_device_add(pcibr_vhdl, EDGE_LBL_CONTROLLER, "pcibr_", &ctlr_vhdl);
-    ASSERT(rc == GRAPH_SUCCESS);
+    ctlr_vhdl = NULL;
+    ctlr_vhdl = hwgraph_register(pcibr_vhdl, EDGE_LBL_CONTROLLER,
+                0, DEVFS_FL_AUTO_DEVNUM,
+                0, 0,
+                S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+                &pcibr_fops, NULL);
+
+    ASSERT(ctlr_vhdl != NULL);
 
     /*
      * decode the nic, and hang its stuff off our
@@ -3606,6 +3693,10 @@
 	pcibr_soft->bs_xbridge = 0;
     }
 
+    nasid = NASID_GET(bridge);
+    scp = &NODEPDA( NASID_TO_COMPACT_NODEID(nasid) )->module->elsc;
+    pcibr_soft->bs_l1sc = scp;
+    pcibr_soft->bs_moduleid = iobrick_module_get(scp);
     pcibr_soft->bsi_err_intr = 0;
 
     /* Bridges up through REV C
@@ -3660,7 +3751,7 @@
     /*
      * Init bridge lock.
      */
-    spinlock_init(&pcibr_soft->bs_lock, "pcibr_loc");
+    spin_lock_init(&pcibr_soft->bs_lock);
 
     /*
      * If we have one, process the hints structure.
@@ -3691,12 +3782,18 @@
 	pcibr_soft->bs_slot[slot].bss_devio.bssd_space = PCIIO_SPACE_NONE;
 	pcibr_soft->bs_slot[slot].bss_d64_base = PCIBR_D64_BASE_UNSET;
 	pcibr_soft->bs_slot[slot].bss_d32_base = PCIBR_D32_BASE_UNSET;
-	pcibr_soft->bs_slot[slot].bss_ext_ates_active = 0;
+	pcibr_soft->bs_slot[slot].bss_ext_ates_active = ATOMIC_INIT(0);
     }
 
     for (ibit = 0; ibit < 8; ++ibit) {
 	pcibr_soft->bs_intr[ibit].bsi_xtalk_intr = 0;
-	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_list = 0;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_soft = pcibr_soft;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_list = NULL;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_stat = 
+							&(bridge->b_int_status);
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_hdlrcnt = 0;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_shared = 0;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_connected = 0;
     }
 
     /*
@@ -3733,7 +3830,7 @@
 	iopaddr_t               xbase;
 	xwidgetnum_t            xport;
 	iopaddr_t               offset;
-	int                     num_entries;
+	int                     num_entries = 0;
 	int                     entry;
 	cnodeid_t		cnodeid;
 	nasid_t			nasid;
@@ -3801,10 +3898,6 @@
 
 	    dirmap = xport << BRIDGE_DIRMAP_W_ID_SHFT;
 
-#ifdef IRIX
-	    dirmap |= BRIDGE_DIRMAP_RMF_64;
-#endif
-
 	    if (xbase)
 		dirmap |= BRIDGE_DIRMAP_OFF & xbase;
 	    else if (offset >= (512 << 20))
@@ -3855,15 +3948,10 @@
 	 * recomparing against BRIDGE_INTERNAL_ATES every
 	 * time.
 	 */
-#ifdef BRINGUP
-	/*
-	 * 082799: for some reason pcibr_init_ext_ate_ram is causing
-	 * a Data Bus Error.  It should be zero anyway so just force it.
-	 */
-	num_entries = 0;
-#else
-	num_entries = pcibr_init_ext_ate_ram(bridge);
-#endif
+	if (is_xbridge(bridge))
+		num_entries = 0;
+	else
+		num_entries = pcibr_init_ext_ate_ram(bridge);
 
 	/* we always have 128 ATEs (512 for Xbridge) inside the chip
 	 * even if disabled for debugging.
@@ -3947,7 +4035,6 @@
 
     pcibr_soft->bsi_err_intr = xtalk_intr;
 
-#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
     /*
      * On IP35 with XBridge, we do some extra checks in pcibr_setwidint
      * in order to work around some addressing limitations.  In order
@@ -3955,9 +4042,6 @@
      * start from a known clean state.
      */
     pcibr_clearwidint(bridge);
-#endif
-
-    printk("pribr_attach:  FIXME Error Interrupt not registered\n");
 
     xtalk_intr_connect(xtalk_intr,
 		       (intr_func_t) pcibr_error_intr_handler,
@@ -4054,13 +4138,13 @@
     }
 #endif
 
-#ifdef IRIX
+#ifdef LATER
     /* If the bridge has been reset then there is no need to reset
      * the individual PCI slots.
      */
     for (slot = 0; slot < 8; ++slot)  
 	/* Reset all the slots */
-	(void)pcibr_slot_reset(pcibr_vhdl,slot);
+	(void)pcibr_slot_reset(pcibr_vhdl, slot);
 #endif
 
     for (slot = 0; slot < 8; ++slot)
@@ -4075,6 +4159,7 @@
 	/* Setup the device register */
 	(void)pcibr_slot_device_init(pcibr_vhdl, slot);
 
+#ifndef __ia64
 #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
     for (slot = 0; slot < 8; ++slot)  
 	/* Set up convenience links */
@@ -4082,6 +4167,7 @@
 		if (pcibr_soft->bs_slot[slot].bss_ninfo > 0) /* if occupied */
 			pcibr_bus_cnvlink(pcibr_info->f_vertex, slot);
 #endif
+#endif
 
     for (slot = 0; slot < 8; ++slot)  
 	/* Setup host/guest relations */
@@ -4091,12 +4177,34 @@
 	/* Initial RRB management */
 	(void)pcibr_slot_initial_rrb_alloc(pcibr_vhdl,slot);
 
-#ifdef dagum
     /* driver attach routines should be called out from generic linux code */
     for (slot = 0; slot < 8; ++slot)  
 	/* Call the device attach */
-	(void)pcibr_slot_call_device_attach(pcibr_vhdl,slot);
-#endif /* dagum */
+	(void)pcibr_slot_call_device_attach(pcibr_vhdl, slot, 0);
+
+    /*
+     * Each Pbrick PCI bus only has slots 1 and 2.   Similarly for
+     * widget 0xe on Ibricks.  Allocate RRB's accordingly.
+     */
+    if (pcibr_soft->bs_moduleid > 0) {
+	switch (MODULE_GET_BTCHAR(pcibr_soft->bs_moduleid)) {
+	case 'p':		/* Pbrick */
+		do_pcibr_rrb_autoalloc(pcibr_soft, 1, 8);
+		do_pcibr_rrb_autoalloc(pcibr_soft, 2, 8);
+		break;
+	case 'i':		/* Ibrick */
+	  	/* port 0xe on the Ibrick only has slots 1 and 2 */
+		if (pcibr_soft->bs_xid == 0xe) {
+			do_pcibr_rrb_autoalloc(pcibr_soft, 1, 8);
+			do_pcibr_rrb_autoalloc(pcibr_soft, 2, 8);
+		}
+		else {
+		    	/* allocate one RRB for the serial port */
+			do_pcibr_rrb_autoalloc(pcibr_soft, 0, 1);
+		}
+		break;
+	} /* switch */
+    }
 
 #ifdef LATER
     if (strstr(nicinfo, XTALK_PCI_PART_NUM)) {
@@ -4119,13 +4227,13 @@
 #endif
     }
 #else
-	printk("pcibr_attach: FIXME to call do_pcibr_rrb_autoalloc nicinfo 0x%p\n", nicinfo);
+	FIXME("pcibr_attach: Call do_pcibr_rrb_autoalloc nicinfo\n");
 #endif
 
     if (aa)
 	    async_attach_add_info(noslot_conn, aa);
 
-    pciio_device_attach(noslot_conn);
+    pciio_device_attach(noslot_conn, 0);
 
 
     /* 
@@ -4166,14 +4274,14 @@
 	printk("pcibr_device_detach called for %p/%d\n",
 		pcibr_vhdl,slot);
 #endif
-	pcibr_device_detach(pcibr_vhdl, slot);
+	pcibr_slot_detach(pcibr_vhdl, slot, 0);
     }
 
     /* Unregister the no-slot connection point */
     pciio_device_info_unregister(pcibr_vhdl,
 				 &(pcibr_soft->bs_noslot_info->f_c));
 
-    spinlock_destroy(&pcibr_soft->bs_lock);
+    spin_lock_destroy(&pcibr_soft->bs_lock);
     kfree(pcibr_soft->bs_name);
     
     /* Error handler gets unregistered when the widget info is 
@@ -4264,7 +4372,7 @@
     size_t                  msize;	/* size of devio(x) mapped area on PCI */
     size_t                  mmask;	/* addr bits stored in Device(x) */
 
-    unsigned                s;
+    unsigned long           s;
 
     s = pcibr_lock(pcibr_soft);
 
@@ -4327,7 +4435,7 @@
 	if (wspace == PCIIO_SPACE_NONE)
 	    goto done;
 
-	/* get pci base and size */
+	/* get PCI base and size */
 	wbase = pcibr_info->f_window[bar].w_base;
 	wsize = pcibr_info->f_window[bar].w_size;
 
@@ -4587,7 +4695,7 @@
     pcibr_piomap_t          pcibr_piomap;
     iopaddr_t               xio_addr;
     xtalk_piomap_t          xtalk_piomap;
-    unsigned                s;
+    unsigned long           s;
 
     /* Make sure that the req sizes are non-zero */
     if ((req_size < 1) || (req_size_max < 1))
@@ -4631,7 +4739,7 @@
     pcibr_piomap->bp_pciaddr = pci_addr;
     pcibr_piomap->bp_mapsz = req_size;
     pcibr_piomap->bp_soft = pcibr_soft;
-    pcibr_piomap->bp_toc[0] = 0;
+    pcibr_piomap->bp_toc[0] = ATOMIC_INIT(0);
 
     if (mapptr) {
 	s = pcibr_lock(pcibr_soft);
@@ -4733,7 +4841,7 @@
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
 
     pciio_piospace_t        piosp;
-    int                     s;
+    unsigned long           s;
 
     iopaddr_t              *pciaddr, *pcilast;
     iopaddr_t               start_addr;
@@ -4751,7 +4859,7 @@
     /*
      * First look if a previously allocated chunk exists.
      */
-    if ((piosp = pcibr_info->f_piospace) != (pciio_piospace_t)0) {
+    if ((piosp = pcibr_info->f_piospace)) {
 	/*
 	 * Look through the list for a right sized free chunk.
 	 */
@@ -4825,7 +4933,7 @@
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast;
 
     pciio_piospace_t        piosp;
-    int                     s;
+    unsigned long           s;
     char                    name[1024];
 
     /*
@@ -4901,7 +5009,7 @@
     iopaddr_t               attributes = 0;
 
     /* Sanity check: Bridge only allows use of VCHAN1 via 64-bit addrs */
-#ifdef IRIX
+#ifdef LATER
     ASSERT_ALWAYS(!(flags & PCIBR_VCHAN1) || (flags & PCIIO_DMA_A64));
 #endif
 
@@ -5031,7 +5139,16 @@
     /* merge in forced flags */
     flags |= pcibr_soft->bs_dma_flags;
 
+#ifdef IRIX
     NEWf(pcibr_dmamap, flags);
+#else
+    /*
+     * On SNIA64, these maps are pre-allocated because pcibr_dmamap_alloc()
+     * can be called within an interrupt thread.
+     */
+    pcibr_dmamap = (pcibr_dmamap_t)get_free_pciio_dmamap(pcibr_soft->bs_vhdl);
+#endif
+
     if (!pcibr_dmamap)
 	return 0;
 
@@ -5162,7 +5279,7 @@
 	    pcibr_dmamap->bd_pci_addr =
 		PCI32_MAPPED_BASE + IOPGSIZE * ate_index;
 	    /*
-	     * for xbridge the byte-swap bit == bit 29 of pci address
+	     * for xbridge the byte-swap bit == bit 29 of PCI address
 	     */
 	    if (pcibr_soft->bs_xbridge) {
 		    if (flags & PCIIO_BYTE_STREAM)
@@ -5201,7 +5318,7 @@
 		bridge_t               *bridge = pcibr_soft->bs_base;
 		volatile unsigned      *cmd_regp;
 		unsigned                cmd_reg;
-		unsigned                s;
+		unsigned long           s;
 
 		pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_SSRAM;
 
@@ -5239,20 +5356,15 @@
     pcibr_soft_t            pcibr_soft = pcibr_dmamap->bd_soft;
     pciio_slot_t            slot = pcibr_dmamap->bd_slot;
 
-#ifdef IRIX
     unsigned                flags = pcibr_dmamap->bd_flags;
-#endif
 
     /* Make sure that bss_ext_ates_active
      * is properly kept up to date.
      */
-#ifdef IRIX
+
     if (PCIBR_DMAMAP_BUSY & flags)
 	if (PCIBR_DMAMAP_SSRAM & flags)
-	    atomicAddInt(&(pcibr_soft->
-			   bs_slot[slot].
-			   bss_ext_ates_active), -1);
-#endif
+	    atomic_dec(&(pcibr_soft->bs_slot[slot]. bss_ext_ates_active));
 
     xtalk_dmamap_free(pcibr_dmamap->bd_xtalk);
 
@@ -5265,7 +5377,9 @@
 		       pcibr_dmamap->bd_ate_count);
 	pcibr_release_device(pcibr_soft, slot, BRIDGE_DEV_PMU_BITS);
     }
+#ifdef IRIX
     DEL(pcibr_dmamap);
+#endif
 }
 
 /*
@@ -5325,7 +5439,6 @@
 /* We are starting to get more complexity
  * surrounding writing ATEs, so pull
  * the writing code into this new function.
- * XXX mail ranga@engr for IP27 prom!
  */
 
 #if PCIBR_FREEZE_TIME
@@ -5342,13 +5455,13 @@
 	   unsigned *cmd_regs)
 {
     pcibr_soft_t            pcibr_soft = pcibr_dmamap->bd_soft;
-#ifdef IRIX
+#ifdef LATER
     int                     dma_slot = pcibr_dmamap->bd_slot;
 #endif
     int                     ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM;
     int                     slot;
 
-    unsigned                s;
+    unsigned long           s;
     unsigned                cmd_reg;
     volatile unsigned      *cmd_lwa;
     unsigned                cmd_lwd;
@@ -5371,27 +5484,22 @@
      */
     s = pcibr_lock(pcibr_soft);
 
-#ifdef IRIX
+#ifdef LATER
     /* just in case pcibr_dmamap_done was not called */
     if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_BUSY) {
 	pcibr_dmamap->bd_flags &= ~PCIBR_DMAMAP_BUSY;
 	if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM)
-	    atomicAddInt(&(pcibr_soft->
-			   bs_slot[dma_slot].
-			   bss_ext_ates_active), -1);
+	    atomic_dec(&(pcibr_soft->bs_slot[dma_slot]. bss_ext_ates_active));
 	xtalk_dmamap_done(pcibr_dmamap->bd_xtalk);
     }
-#endif
+#endif	/* LATER */
 #if PCIBR_FREEZE_TIME
     *freeze_time_ptr = get_timestamp();
 #endif
 
     cmd_lwa = 0;
     for (slot = 0; slot < 8; ++slot)
-	if (pcibr_soft->
-	    bs_slot[slot].
-	    bss_ext_ates_active) {
-
+	if (atomic_read(&pcibr_soft->bs_slot[slot].bss_ext_ates_active)) {
 	    cmd_reg = pcibr_soft->
 		bs_slot[slot].
 		bss_cmd_shadow;
@@ -5418,9 +5526,7 @@
 
 	    /* Flush all the write buffers in the bridge */
 	    for (slot = 0; slot < 8; ++slot)
-		    if (pcibr_soft->
-			bs_slot[slot].
-			bss_ext_ates_active) {
+		    if (atomic_read(&pcibr_soft->bs_slot[slot].bss_ext_ates_active)) {
 			    /* Flush the write buffer associated with this
 			     * PCI device which might be using dma map RAM.
 			     */
@@ -5462,9 +5568,7 @@
 	 unsigned s)
 {
     pcibr_soft_t            pcibr_soft = pcibr_dmamap->bd_soft;
-#ifdef IRIX
     int                     dma_slot = pcibr_dmamap->bd_slot;
-#endif
     int                     slot;
     bridge_t               *bridge = pcibr_soft->bs_base;
     int                     ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM;
@@ -5486,11 +5590,7 @@
 	    bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = cmd_reg;
 
     pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_BUSY;
-#ifdef IRIX
-    atomicAddInt(&(pcibr_soft->
-		   bs_slot[dma_slot].
-		   bss_ext_ates_active), 1);
-#endif
+    atomic_inc(&(pcibr_soft->bs_slot[dma_slot]. bss_ext_ates_active));
 
 #if PCIBR_FREEZE_TIME
     freeze_time = get_timestamp() - freeze_time_start;
@@ -5685,11 +5785,7 @@
 		  unsigned flags)
 {
     pcibr_soft_t            pcibr_soft;
-#ifdef IRIX
-    bridge_t               *bridge;
-#else
     bridge_t               *bridge=NULL;
-#endif
 
     unsigned                al_flags = (flags & PCIIO_NOSLEEP) ? AL_NOSLEEP : 0;
     int                     inplace = flags & PCIIO_INPLACE;
@@ -5699,19 +5795,11 @@
     size_t                  length;
     iopaddr_t               offset;
     unsigned                direct64;
-#ifdef IRIX
-    int                     ate_index;
-    int                     ate_count;
-    int                     ate_total = 0;
-    bridge_ate_p            ate_ptr;
-    bridge_ate_t            ate_proto;
-#else
     int                     ate_index = 0;
     int                     ate_count = 0;
     int                     ate_total = 0;
     bridge_ate_p            ate_ptr = (bridge_ate_p)0;
     bridge_ate_t            ate_proto = (bridge_ate_t)0;
-#endif
     bridge_ate_t            ate_prev;
     bridge_ate_t            ate;
     alenaddr_t              xio_addr;
@@ -5899,16 +5987,12 @@
      * between _addr/_list and _done, but Hub does.
      */
 
-#ifdef IRIX
     if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_BUSY) {
 	pcibr_dmamap->bd_flags &= ~PCIBR_DMAMAP_BUSY;
 
 	if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM)
-	    atomicAddInt(&(pcibr_dmamap->bd_soft->
-			   bs_slot[pcibr_dmamap->bd_slot].
-			   bss_ext_ates_active), -1);
+	    atomic_dec(&(pcibr_dmamap->bd_soft->bs_slot[pcibr_dmamap->bd_slot]. bss_ext_ates_active));
     }
-#endif
 
     xtalk_dmamap_done(pcibr_dmamap->bd_xtalk);
 }
@@ -6332,11 +6416,7 @@
 	 */
 	if (xio_port == pcibr_soft->bs_xid) {
 	    pci_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, xio_size);
-#ifdef IRIX
-	    if (pci_addr == NULL)
-#else
 	    if ( (pci_addr == (alenaddr_t)NULL) )
-#endif
 		goto fail;
 	} else if (direct64) {
 	    ASSERT(xio_port != 0);
@@ -6371,11 +6451,7 @@
 	}
     }
 
-#ifdef IRIX
-    if (relbits)
-#else
     if (relbits) {
-#endif
 	if (direct64) {
 	    slotp->bss_d64_flags = flags;
 	    slotp->bss_d64_base = pci_base;
@@ -6383,9 +6459,7 @@
 	    slotp->bss_d32_flags = flags;
 	    slotp->bss_d32_base = pci_base;
 	}
-#ifndef IRIX
     }
-#endif
     if (!inplace)
 	alenlist_done(xtalk_alenlist);
 
@@ -6480,26 +6554,155 @@
     return bbits;
 }
 
-#ifdef IRIX
+
+/*
+ *	Get the next wrapper pointer queued in the interrupt circular buffer.
+ */
+#ifdef KERNEL_THREADS
+pcibr_intr_wrap_t
+pcibr_wrap_get(pcibr_intr_cbuf_t cbuf)
+{
+    pcibr_intr_wrap_t	wrap;
+
+	if (cbuf->ib_in == cbuf->ib_out)
+	    PRINT_PANIC("pcibr intr circular buffer empty, cbuf=0x%x, ib_in=ib_out=%d\n",
+		cbuf, cbuf->ib_out);
+
+	wrap = cbuf->ib_cbuf[cbuf->ib_out++];
+	cbuf->ib_out = cbuf->ib_out % IBUFSIZE;
+	return(wrap);
+}
+
+/* 
+ *	Queue a wrapper pointer in the interrupt circular buffer.
+ */
+void
+pcibr_wrap_put(pcibr_intr_wrap_t wrap, pcibr_intr_cbuf_t cbuf)
+{
+	int	in;
+	unsigned long	s;
+
+	/*
+	 * Multiple CPUs could be executing this code simultaneously
+	 * if a handler has registered multiple interrupt lines and
+	 * the interrupts are directed to different CPUs.
+	 */
+	s = mutex_spinlock(&cbuf->ib_lock);
+	in = (cbuf->ib_in + 1) % IBUFSIZE;
+	if (in == cbuf->ib_out) 
+	    PRINT_PANIC("pcibr intr circular buffer full, cbuf=0x%x, ib_in=%d\n",
+		cbuf, cbuf->ib_in);
+
+	cbuf->ib_cbuf[cbuf->ib_in] = wrap;
+	cbuf->ib_in = in;
+	mutex_spinunlock(&cbuf->ib_lock, s);
+	return;
+}
+#endif	/* KERNEL_THREADS */
+
+/*
+ *	There are end cases where a deadlock can occur if interrupt 
+ *	processing completes and the Bridge b_int_status bit is still set.
+ *
+ *	One scenerio is if a second PCI interrupt occurs within 60ns of
+ *	the previous interrupt being cleared. In this case the Bridge
+ *	does not detect the transition, the Bridge b_int_status bit
+ *	remains set, and because no transition was detected no interrupt
+ *	packet is sent to the Hub/Heart.
+ *
+ *	A second scenerio is possible when a b_int_status bit is being
+ *	shared by multiple devices:
+ *						Device #1 generates interrupt
+ *						Bridge b_int_status bit set
+ *						Device #2 generates interrupt
+ *		interrupt processing begins
+ *		  ISR for device #1 runs and
+ *			clears interrupt
+ *						Device #1 generates interrupt
+ *		  ISR for device #2 runs and
+ *			clears interrupt
+ *						(b_int_status bit still set)
+ *		interrupt processing completes
+ *		  
+ *	Interrupt processing is now complete, but an interrupt is still
+ *	outstanding for Device #1. But because there was no transition of
+ *	the b_int_status bit, no interrupt packet will be generated and
+ *	a deadlock will occur.
+ *
+ *	To avoid these deadlock situations, this function is used
+ *	to check if a specific Bridge b_int_status bit is set, and if so,
+ *	cause the setting of the corresponding interrupt bit.
+ *
+ *	On a XBridge (IP35), we do this by writing the appropriate Bridge Force 
+ *	Interrupt register.
+ */
+void
+pcibr_force_interrupt(pcibr_intr_wrap_t wrap)
+{
+	unsigned	bit;
+	pcibr_soft_t    pcibr_soft = wrap->iw_soft;
+	bridge_t       *bridge = pcibr_soft->bs_base;
+	cpuid_t cpuvertex_to_cpuid(devfs_handle_t vhdl);
+
+	bit = wrap->iw_intr;
+
+	if (pcibr_soft->bs_xbridge) {
+	    bridge->b_force_pin[bit].intr = 1;
+	} else if ((1 << bit) & *wrap->iw_stat) {
+	    cpuid_t	    cpu;
+	    unsigned        intr_bit;
+	    xtalk_intr_t    xtalk_intr =
+				pcibr_soft->bs_intr[bit].bsi_xtalk_intr;
+
+	    intr_bit = (short) xtalk_intr_vector_get(xtalk_intr);
+	    cpu = cpuvertex_to_cpuid(xtalk_intr_cpu_get(xtalk_intr));
+	    REMOTE_CPU_SEND_INTR(cpu, intr_bit);
+	}
+}
+
 /* Wrapper for pcibr interrupt threads. */
+#ifdef KERNEL_THREADS
 static void
 pcibr_intrd(pcibr_intr_t intr)
 {
+    pcibr_intr_wrap_t	wrap;
+
 	/* Called on each restart */
 	ASSERT(cpuid() == intr->bi_mustruncpu);
 
 #ifdef ITHREAD_LATENCY
-	xthread_update_latstats(intr->bi_tinfo->thd_latstats);
+	xthread_update_latstats(intr->bi_tinfo.thd_latstats);
 #endif /* ITHREAD_LATENCY */
 
 	ASSERT(intr->bi_func != NULL);
 	intr->bi_func(intr->bi_arg);		/* Invoke the interrupt handler */
 
+	/*
+	 * The pcibr_intrd thread needs access to the wrapper struct
+	 * specific to the current interrupt it is processing. Because
+	 * multiple calls/wakeups to the thread could be queued, each
+	 * potentially from a different interrupt line (PCIIO_INTR_LINE_A,
+	 * etc), multiple wrapper struct pointers need to be queued. This 
+	 * is done via a circular buffer of wrapper struct pointers. 
+	 */
+	wrap = pcibr_wrap_get(&intr->bi_ibuf);
+
+	/* 
+	 * The interrupt handler has completed. Now decrement the running
+	 * count tracking the number of handlers still running for this line.
+	 * If this was the last handler to complete (i.e., iw_hdlrcnt == 0),
+	 * avoid a potential deadlock condition and ensure that another
+	 * interrupt will occur if the Bridge b_int_status bit is still
+	 * set. 
+	 */
+	atomicAddInt(&(wrap->iw_hdlrcnt), -1);
+	if (wrap->iw_hdlrcnt == 0)
+		pcibr_force_interrupt(wrap);
+
 	ipsema(&intr->bi_tinfo.thd_isync);	/* Sleep 'till next interrupt */
 	/* NOTREACHED */
 }
 
-
 static void
 pcibr_intrd_start(pcibr_intr_t intr)
 {
@@ -6519,14 +6722,16 @@
 	char thread_name[32];
 
 	sprintf(thread_name, "pcibr_intrd[0x%x]", bridge_levels);
+	thread_name[IT_NAMELEN-1] = '\0';
 
 	/* XXX need to adjust priority whenever an interrupt is connected */
+	intr->bi_tinfo.thd_pri = intr_swlevel;
 	atomicSetInt(&intr->bi_tinfo.thd_flags, THD_ISTHREAD | THD_REG);
 	xthread_setup(thread_name, intr_swlevel, &intr->bi_tinfo,
 			(xt_func_t *)pcibr_intrd_start,
 			(void *)intr);
 }
-#endif	/* IRIX */
+#endif	/* KERNEL_THREADS */
 
 
 
@@ -6542,13 +6747,16 @@
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast;
     devfs_handle_t            xconn_vhdl = pcibr_soft->bs_conn;
     bridge_t               *bridge = pcibr_soft->bs_base;
-    int                     is_threaded;
+    int                     is_threaded = 0;
+#ifdef KERNEL_THREADS
+    cpuid_t		    mustruncpu = CPU_NONE;
+    cpuid_t		    old_intrcpu = CPU_NONE;
+#endif
     int                     thread_swlevel;
 
     xtalk_intr_t           *xtalk_intr_p;
     pcibr_intr_t           *pcibr_intr_p;
     pcibr_intr_list_t      *intr_list_p;
-    pcibr_intr_wrap_t      *intr_wrap_p;
 
     unsigned                pcibr_int_bits;
     unsigned                pcibr_int_bit;
@@ -6557,7 +6765,6 @@
     pcibr_intr_t            pcibr_intr;
     pcibr_intr_list_t       intr_entry;
     pcibr_intr_list_t       intr_list;
-    pcibr_intr_wrap_t       intr_wrap;
     bridgereg_t             int_dev;
 
 #if DEBUG && INTR_DEBUG
@@ -6576,9 +6783,29 @@
 	return NULL;
 
     if (dev_desc) {
+	cpuid_t intr_target_from_desc(device_desc_t, int);
+
+#ifdef KERNEL_THREADS
 	is_threaded = !(device_desc_flags_get(dev_desc) & D_INTR_NOTHREAD);
-	if (is_threaded)
+	if (is_threaded) {
+	    /*
+	     * If the device descriptor contains interrupt target info,
+	     * save the CPU requested. This is the CPU the pcibr_intrd
+	     * thread will be set to run on. 
+	     *
+	     * We need to get the interrupt target info at this time, because
+	     * the original intr_target value can be overwritten, as part of
+	     * the xtalk_intr_alloc_nothd() call, with the actual interrupt CPU.
+	     * This can be different than the requested CPU if the lower layers
+	     * could not direct the hardware interrupt to the requested CPU. 
+	     * Regardless of which CPU processes the hardware interrupt, the 
+	     * ISR thread will still be setup to run on the CPU originally 
+	     * requested.
+	     */
+		mustruncpu = intr_target_from_desc(dev_desc, SUBNODE_ANY);
 		thread_swlevel = device_desc_intr_swlevel_get(dev_desc);
+	}
+#endif	/* KERNEL_THREADS */
     } else {
 	extern int default_intr_pri;
 
@@ -6594,6 +6821,11 @@
     pcibr_intr->bi_arg = 0;		/* unset until connect */
     pcibr_intr->bi_flags = is_threaded ? 0 : PCIIO_INTR_NOTHREAD;
     pcibr_intr->bi_mustruncpu = CPU_NONE;
+#ifdef KERNEL_THREADS
+    pcibr_intr->bi_ibuf.ib_in = 0;
+    pcibr_intr->bi_ibuf.ib_out = 0;
+#endif
+    mutex_spinlock_init(&pcibr_intr->bi_ibuf.ib_lock);
 
     pcibr_int_bits = pcibr_soft->bs_intr_bits((pciio_info_t)pcibr_info, lines);
 
@@ -6626,7 +6858,17 @@
 		 *    single Bridge. (IP35-specific code forces this, and we
 		 *    verify in pcibr_setwidint.)
 		 */
-		xtalk_intr = xtalk_intr_alloc(xconn_vhdl, dev_desc, owner_dev);
+
+		/*
+		 * All code dealing with threaded PCI interrupt handlers
+		 * is located at the pcibr level. Because of this,
+		 * we always want the lower layers (hub/heart_intr_alloc, 
+		 * intr_level_connect) to treat us as non-threaded so we
+		 * don't set up a duplicate threaded environment. We make
+		 * this happen by calling a special xtalk interface.
+		 */
+		xtalk_intr = xtalk_intr_alloc_nothd(xconn_vhdl, dev_desc, 
+			owner_dev);
 #if DEBUG && INTR_DEBUG
 		printk("%v: xtalk_intr=0x%X\n", xconn_vhdl, xtalk_intr);
 #endif
@@ -6690,32 +6932,64 @@
 		}
 	    }
 
-	    /*
-	     * For threaded drivers, set the interrupt thread to run wherever
-	     * the interrupt is targeted.
-	     */
-#ifdef notyet
+#ifdef KERNEL_THREADS
 	    if (is_threaded) {
-		cpuid_t old_mustrun = pcibr_intr->bi_mustruncpu;
-		pcibr_intr->bi_mustruncpu = cpuvertex_to_cpuid(xtalk_intr_cpu_get(xtalk_intr));
-		ASSERT(pcibr_intr->bi_mustruncpu >= 0);
+		cpuid_t intrcpu = cpuvertex_to_cpuid(xtalk_intr_cpu_get(xtalk_intr));
 
 		/*
-		 * This is possible, but very unlikely: It means that 2 (or more) interrupts
-		 * originating on a single Bridge and used by a single device were unable to
-		 * find sufficient xtalk interrupt resources that would allow them all to be
-		 * handled by the same CPU.  If someone tries to target lots of interrupts to
-		 * a single CPU, we might hit this case.  Things should still operate correctly,
-		 * but it's a sub-optimal configuration.
+		 * It is possible that 2 (or more) interrupts originating on a
+		 * single Bridge and used by a single device were assigned to
+		 * different CPUs. If this occurs issue a warning message for
+		 * this sub-optimal configuration. There are two ways this 
+		 * could happen:
+		 *
+		 *  - There were insufficient xtalk interrupt resources to
+		 *    allow all interrupts to be assigned to the same CPU.
+		 *    This is an unlikely case, but could happen if someone
+		 *    tries to target a lot of interrupts to a single CPU.
+		 *
+		 * - If there is no device descriptor associated with this
+		 *   device, the xtalk/hub/heart layers will not know to
+		 *   assign the same CPU to any additional interrupts this
+		 *   driver has specified, and will perform the normal load
+		 *   leveling of interrupts across CPUs.
+		 *   (The lower layers store the CPU assigned to the first
+		 *   interrupt in the device desc, if present, and then when
+		 *   called again for additional interrupts for the same device,
+		 *   use this information to assign the same CPU to these
+		 *   interrupts.)
 		 */
-		if ((old_mustrun != CPU_NONE) && (old_mustrun != pcibr_intr->bi_mustruncpu)) {
-#ifdef SUPPORT_PRINTING_V_FORMAT
-			PRINT_WARNING( "Conflict on where to schedule interrupts for %v\n", pconn_vhdl);
+		if ((old_intrcpu != CPU_NONE) && (old_intrcpu != intrcpu)) {
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+			PRINT_WARNING("Conflict on where to schedule interrupts for %v\n", pconn_vhdl);
+#else
+			PRINT_WARNING("Conflict on where to schedule interrupts for 0x%x\n", pconn_vhdl);
 #endif
-			PRINT_WARNING( "(on cpu %d or on cpu %d)\n", old_mustrun, pcibr_intr->bi_mustruncpu);
+			PRINT_WARNING("(on cpu %d or on cpu %d), cpu %d used\n", old_intrcpu, intrcpu, intrcpu);
+		}
+		if (old_intrcpu == CPU_NONE)
+			old_intrcpu = intrcpu;
+	    /*
+	     * For threaded drivers, set the interrupt thread to run wherever
+	     * the interrupt is targeted, or where requested in the dev_desc.
+	     */
+		if (mustruncpu != CPU_NONE) {
+			pcibr_intr->bi_mustruncpu = mustruncpu;
+			if (mustruncpu != intrcpu) {
+				PRINT_WARNING("Request to target PCI interrupts to CPU %d could not\n"
+                		"      be satisfied, CPU %d used. However, interrupt thread\n"
+                		"      pcibr_intrd will run on CPU %d as requested.\n"
+                		"      %v (0x%x)\n",
+                		mustruncpu, intrcpu, mustruncpu, owner_dev,
+				owner_dev);
+			}
+		} else {
+			pcibr_intr->bi_mustruncpu = intrcpu;
 		}
+		ASSERT(pcibr_intr->bi_mustruncpu >= 0);
+
 	    }
-#endif
+#endif	/* KERNEL_THREADS */
 
 	    pcibr_intr->bi_ibits |= 1 << pcibr_int_bit;
 
@@ -6723,8 +6997,20 @@
 	    intr_entry->il_next = NULL;
 	    intr_entry->il_intr = pcibr_intr;
 	    intr_entry->il_wrbf = &(bridge->b_wr_req_buf[pciio_slot].reg);
+	    intr_list_p = 
+		&pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_list;
+#if DEBUG && INTR_DEBUG
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+	    printk("0x%x: Bridge bit %d wrap=0x%x\n",
+		pconn_vhdl, pcibr_int_bit,
+		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap);
+#else
+	    printk("%v: Bridge bit %d wrap=0x%x\n",
+		pconn_vhdl, pcibr_int_bit,
+		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap);
+#endif
+#endif
 
-	    intr_list_p = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_list;
 	    if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {
 		/* we are the first interrupt on this bridge bit.
 		 */
@@ -6751,29 +7037,12 @@
 	    intr_list_p = &intr_list->il_next;
 	    if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {
 		/* we are the new second interrupt on this bit.
-		 * switch to local wrapper.
 		 */
+		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared = 1;
 #if DEBUG && INTR_DEBUG
 		printk("%v INT 0x%x (bridge bit %d) is new SECOND\n",
 			pconn_vhdl, pcibr_int_bits, pcibr_int_bit);
 #endif
-		NEW(intr_wrap);
-		intr_wrap->iw_soft = pcibr_soft;
-		intr_wrap->iw_stat = &(bridge->b_int_status);
-		intr_wrap->iw_intr = 1 << pcibr_int_bit;
-		intr_wrap->iw_list = intr_list;
-		intr_wrap_p = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
-		if (!compare_and_swap_ptr((void **) intr_wrap_p, NULL, intr_wrap)) {
-		    /* someone else set up the wrapper.
-		     */
-		    DEL(intr_wrap);
-		    continue;
-#if DEBUG && INTR_DEBUG
-		} else {
-		    printk("%v bridge bit %d wrapper state created\n",
-			    pconn_vhdl, pcibr_int_bit);
-#endif
-		}
 		continue;
 	    }
 	    while (1) {
@@ -6807,13 +7076,13 @@
 	}
     }
 
-#ifdef IRIX
+#ifdef KERNEL_THREADS
     if (is_threaded) {
 	/* Set pcibr_intr->bi_tinfo */
 	pcibr_thread_setup(pcibr_intr, pcibr_int_bits, thread_swlevel);
 	ASSERT(!(pcibr_intr->bi_flags & PCIIO_INTR_CONNECTED));
     }
-#endif
+#endif	/* KERNEL_THREADS */
 
 #if DEBUG && INTR_DEBUG
     printk("%v pcibr_intr_alloc complete\n", pconn_vhdl);
@@ -6832,13 +7101,13 @@
     pcibr_soft_t            pcibr_soft = pcibr_intr->bi_soft;
     unsigned                pcibr_int_bit;
     pcibr_intr_list_t       intr_list;
-    pcibr_intr_wrap_t	    intr_wrap;
+    int			    intr_shared;
     xtalk_intr_t	    *xtalk_intrp;
 
     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++) {
 	if (pcibr_int_bits & (1 << pcibr_int_bit)) {
 	    for (intr_list = 
-		     pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_list;
+		     pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_list;
 		 intr_list != NULL;
 		 intr_list = intr_list->il_next)
 		if (compare_and_swap_ptr((void **) &intr_list->il_intr, 
@@ -6852,10 +7121,11 @@
 	    /* If this interrupt line is not being shared between multiple
 	     * devices release the xtalk interrupt resources.
 	     */
-	    intr_wrap = 
-		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
+	    intr_shared = 
+		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared;
 	    xtalk_intrp = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr;
-	    if ((intr_wrap == NULL) && (*xtalk_intrp)) {
+
+	    if ((!intr_shared) && (*xtalk_intrp)) {
 
 		bridge_t 	*bridge = pcibr_soft->bs_base;
 		bridgereg_t	int_dev;
@@ -6900,7 +7170,7 @@
     unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;
     unsigned                pcibr_int_bit;
     bridgereg_t             b_int_enable;
-    unsigned                s;
+    unsigned long           s;
 
     if (pcibr_intr == NULL)
 	return -1;
@@ -6924,59 +7194,29 @@
 	if (pcibr_int_bits & (1 << pcibr_int_bit)) {
 	    pcibr_intr_wrap_t       intr_wrap;
 	    xtalk_intr_t            xtalk_intr;
-	    int                    *setptr;
 
 	    xtalk_intr = pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr;
 
-	    /* if we have no wrap structure,
-	     * tell xtalk to deliver the interrupt
-	     * directly to the client.
+	    intr_wrap = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
+	    /*
+	     * If this interrupt line is being shared and the connect has
+	     * already been done, no need to do it again.
 	     */
-	    intr_wrap = pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
-	    if (intr_wrap == NULL) {
-		xtalk_intr_connect(xtalk_intr,
-				   (intr_func_t) intr_func,
-				   (intr_arg_t) intr_arg,
-				   (xtalk_intr_setfunc_t) pcibr_setpciint,
-				   (void *) &(bridge->b_int_addr[pcibr_int_bit].addr),
-				   thread);
-#if DEBUG && INTR_DEBUG
-		printk("%v bridge bit %d routed by xtalk\n",
-			pcibr_intr->bi_dev, pcibr_int_bit);
-#endif
+	    if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected)
 		continue;
-	    }
-
-	    setptr = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_wrap_set;
-	    if (*setptr)
-		continue;
-
 
-	    /* We have a wrap structure, so we're sharing a Bridge interrupt level */
-
-	    xtalk_intr_disconnect(xtalk_intr); /* Disconnect old interrupt */
 
 	    /*
-		If the existing xtalk_intr was allocated without the NOTHREAD flag,
-		we need to allocate a new one that's NOTHREAD, and connect to the
-		new one.   pcibr_intr_list_func expects to run at interrupt level
-		rather than in a thread.  With today's devices, this can't happen,
-		so let's punt on writing the code till we need it (probably never).
-		Instead, just ASSERT that we're a NOTHREAD xtalk_intr.
-	    */
-#ifdef IRIX
-	    ASSERT_ALWAYS(!(pcibr_intr->bi_flags & PCIIO_INTR_NOTHREAD) ||
-			xtalk_intr_flags_get(xtalk_intr) & XTALK_INTR_NOTHREAD);
-#endif
-
-	    /* Use the wrapper dispatch function to handle shared Bridge interrupts */
+	     * Use the pcibr wrapper function to handle all Bridge interrupts
+	     * regardless of whether the interrupt line is shared or not.
+	     */
 	    xtalk_intr_connect(xtalk_intr,
-			       pcibr_intr_list_func,
+				pcibr_intr_func,
 			       (intr_arg_t) intr_wrap,
 			       (xtalk_intr_setfunc_t) pcibr_setpciint,
 			       (void *) &(bridge->b_int_addr[pcibr_int_bit].addr),
 			       0);
-	    *setptr = 1;
+	    pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected = 1;
 
 #if DEBUG && INTR_DEBUG
 	    printk("%v bridge bit %d wrapper connected\n",
@@ -7001,9 +7241,9 @@
     bridge_t               *bridge = pcibr_soft->bs_base;
     unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;
     unsigned                pcibr_int_bit;
-    pcibr_intr_wrap_t       intr_wrap;
+    pcibr_intr_wrap_t	    intr_wrap;
     bridgereg_t             b_int_enable;
-    unsigned                s;
+    unsigned long           s;
 
     /* Stop calling the function. Now.
      */
@@ -7021,7 +7261,7 @@
      */
     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)
 	if ((pcibr_int_bits & (1 << pcibr_int_bit)) &&
-	    (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_wrap_set))
+	    (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared))
 	    pcibr_int_bits &= ~(1 << pcibr_int_bit);
     if (!pcibr_int_bits)
 	return;
@@ -7035,26 +7275,32 @@
 
     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)
 	if (pcibr_int_bits & (1 << pcibr_int_bit)) {
-	    /* if we have set up the share wrapper,
+	    /* if the interrupt line is now shared,
 	     * do not disconnect it.
 	     */
-	    if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_wrap_set)
+	    if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared)
 		continue;
 
 	    xtalk_intr_disconnect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr);
+	    pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected = 0;
+
+#if DEBUG && INTR_DEBUG
+	    printk("%s: xtalk disconnect done for Bridge bit %d\n",
+		pcibr_soft->bs_name, pcibr_int_bit);
+#endif
 
-	    /* if we have a share wrapper state,
+	    /* if we are sharing the interrupt line,
 	     * connect us up; this closes the hole
-	     * where the connection of the wrapper
+	     * where the another pcibr_intr_alloc()
 	     * was in progress as we disconnected.
 	     */
-	    intr_wrap = pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
-	    if (intr_wrap == NULL) 
+	    intr_wrap = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
+	    if (!pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared)
 		continue;
 
 
 	    xtalk_intr_connect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr,
-			       pcibr_intr_list_func,
+			       pcibr_intr_func,
 			       (intr_arg_t) intr_wrap,
 			       (xtalk_intr_setfunc_t) pcibr_setpciint,
 			       (void *) &(bridge->b_int_addr[pcibr_int_bit].addr),
@@ -7168,7 +7414,7 @@
 	bridge->b_int_enable |= ~BRIDGE_IMR_INT_MSK;
 
     } else {
-	/* routing a pci device interrupt.
+	/* routing a PCI device interrupt.
 	 * targ and low 38 bits of addr must
 	 * be the same as the already set
 	 * value for the widget error interrupt.
@@ -7187,46 +7433,71 @@
     bridge->b_wid_tflush;		/* wait until Bridge PIO complete */
 }
 
+
+/*
+ * pcibr_intr_func()
+ *
+ * This is the pcibr interrupt "wrapper" function that is called,
+ * in interrupt context, to initiate the interrupt handler(s) registered
+ * (via pcibr_intr_alloc/connect) for the occuring interrupt. Non-threaded 
+ * handlers will be called directly, and threaded handlers will have their 
+ * thread woken up.
+ */
 void
-pcibr_intr_list_func(intr_arg_t arg)
+pcibr_intr_func(intr_arg_t arg)
 {
     pcibr_intr_wrap_t       wrap = (pcibr_intr_wrap_t) arg;
-    reg_p                   statp = wrap->iw_stat;
-    bridgereg_t             mask = wrap->iw_intr;
     reg_p                   wrbf;
-    pcibr_intr_list_t       list;
-    pcibr_intr_t            intr;
     intr_func_t             func;
+    pcibr_intr_t            intr;
+    pcibr_intr_list_t       list;
     int                     clearit;
-    int                     thread_count = 0;
+#ifdef KERNEL_THREADS
+    int			    do_nonthreaded = 0;
+    int			    do_threaded = 1;
+    int			    is_threaded = 0;
+#else
+    int			    do_nonthreaded = 1;
+    int			    do_threaded = 0;
+    int			    is_threaded = 0;
+#endif
+    int			    nonthreaded_count = 0;
+    int			    x = 0;
+
+	/*
+	 * If any handler is still running from a previous interrupt
+	 * just return. If there's a need to call the handler(s) again,
+	 * another interrupt will be generated either by the device or by
+	 * pcibr_force_interrupt().
+	 */
+
+	if (wrap->iw_hdlrcnt) {
+		return;
+	}
 
     /*
-     * Loop until either
-     * 1) All interrupts have been removed by direct-called interrupt handlers OR
-     * 2) We've woken up at least one interrupt thread that will presumably clear
-     *    Bridge interrupt bits
+     * Call all interrupt handlers registered.
+     * First, the pcibr_intrd threads for any threaded handlers will be
+     * awoken, then any non-threaded handlers will be called sequentially.
      */
 	
-    while ((!thread_count) && (mask & *statp)) {
 	clearit = 1;
-	for (list = wrap->iw_list;
-	     list != NULL;
-	     list = list->il_next) {
-	    if ((intr = list->il_intr) &&
-		(intr->bi_flags & PCIIO_INTR_CONNECTED)) {
-    		int is_threaded;
+	while (do_threaded || do_nonthreaded) {
+	    for (list = wrap->iw_list; list != NULL; list = list->il_next) {
+		if ((intr = list->il_intr) &&
+		    (intr->bi_flags & PCIIO_INTR_CONNECTED)) {
 
-		ASSERT(intr->bi_func);
+		    ASSERT(intr->bi_func);
 
 		/*
 		 * This device may have initiated write
 		 * requests since the bridge last saw
 		 * an edge on this interrupt input; flushing
-		 * the buffer here should help but may not
-		 * be sufficient if we get more requests after
-		 * the flush, followed by the card deciding
-		 * it wants service, before the interrupt
-		 * handler checks to see if things need
+		 * the buffer prior to invoking the handler
+		 * should help but may not be sufficient if we 
+		 * get more requests after the flush, followed
+		 * by the card deciding it wants service, before
+		 * the interrupt handler checks to see if things need
 		 * to be done.
 		 *
 		 * There is a similar race condition if
@@ -7238,28 +7509,96 @@
 		 * has completed, but before observing the
 		 * contents of memory?
 		 */
-#ifdef IRIX
-		if (wrbf = list->il_wrbf)
+
+#ifdef KERNEL_THREADS
+		    is_threaded = !(intr->bi_flags & PCIIO_INTR_NOTHREAD);
+		    if (!is_threaded) {
+			nonthreaded_count++;
+		    }
+
+		    if ((do_threaded) && (is_threaded)) {
+			/* Only need to flush write buffers if sharing */
+
+			if ((wrap->iw_shared) && (wrbf = list->il_wrbf)) {
+			    if (x = *wrbf)	/* write request buffer flush */
+#ifdef SUPPORT_PRINTING_V_FORMAT
+				PRINT_ALERT("pcibr_intr_func %v: \n"
+				    "write buffer flush failed, wrbf=0x%x\n", 
+				    list->il_intr->bi_dev, wrbf);
 #else
-		if ((wrbf = list->il_wrbf))
+				PRINT_ALERT("pcibr_intr_func 0x%x: \n"
+				    "write buffer flush failed, wrbf=0x%x\n", 
+				    list->il_intr->bi_dev, wrbf);
 #endif
-		    (void) *wrbf;	/* write request buffer flush */
+			}
+
+			/*
+			 * Keep a running count of the number of interrupt
+			 * handlers that have yet to complete. 
+			 */
+			atomicAddInt(&(wrap->iw_hdlrcnt), 1);
+
+			/* 
+			 * Prior to waking up pcibr_intrd, a pointer to the 
+			 * wrapper struct corresponding to the interrupt taken
+			 * needs to be queued in the interrupt circular buffer.
+			 * The pcibr_intrd thread needs the wrapper pointer in
+			 * order to decrement the handler count (iw_hdlrcnt).
+			 */
+			pcibr_wrap_put(wrap, &intr->bi_ibuf);
+#ifdef ITHREAD_LATENCY
+			xthread_set_istamp(intr->bi_tinfo.thd_latstats);
+#endif /* ITHREAD_LATENCY */
+		     	up(&intr->bi_tinfo.thd_isync); 
+		    } else
+#endif	/* KERNEL_THREADS */
+			if ((do_nonthreaded) && (!is_threaded)) {
+			/* Non-threaded. 
+			 * Call the interrupt handler at interrupt level
+			 */
 
-		is_threaded = !(intr->bi_flags & PCIIO_INTR_NOTHREAD);
+			/* Only need to flush write buffers if sharing */
 
-		if (is_threaded) {
-			thread_count++;
-#ifdef IRIX
-			icvsema(&intr->bi_tinfo.thd_isync, intr->bi_tinfo.thd_pri,
-				NULL, NULL, NULL);
+			if ((wrap->iw_shared) && (wrbf = list->il_wrbf)) {
+			    if ((x = *wrbf))	/* write request buffer flush */
+#ifdef SUPPORT_PRINTING_V_FORMAT
+				PRINT_ALERT("pcibr_intr_func %v: \n"
+				    "write buffer flush failed, wrbf=0x%x\n", 
+				    list->il_intr->bi_dev, wrbf);
+#else
+				PRINT_ALERT("pcibr_intr_func %p: \n"
+				    "write buffer flush failed, wrbf=0x%x\n", 
+				    list->il_intr->bi_dev, wrbf);
 #endif
-		} else {
-			/* Non-threaded.  Call the interrupt handler at interrupt level */
+			}
+
 			func = intr->bi_func;
 			func(intr->bi_arg);
+		    }
+
+		    clearit = 0;
 		}
+	    }
+
+	    if (do_threaded) {
+		/* 
+		 * All threaded handlers have been called;
+		 * next do non-threaded, if any.
+		 */
+		do_threaded = 0;
 
-		clearit = 0;
+		if (nonthreaded_count)
+			do_nonthreaded = 1;
+	    } else {
+		do_nonthreaded = 0;
+		/*
+		 * If the non-threaded handler was the last to complete,
+		 * (i.e., no threaded handlers still running) force an
+		 * interrupt to avoid a potential deadlock situation.
+		 */
+		if (wrap->iw_hdlrcnt == 0) {
+			pcibr_force_interrupt(wrap);
+		}
 	    }
 	}
 
@@ -7275,7 +7614,8 @@
 	    pcibr_soft_t            pcibr_soft = wrap->iw_soft;
 	    bridge_t               *bridge = pcibr_soft->bs_base;
 	    bridgereg_t             b_int_enable;
-	    unsigned                s;
+	    bridgereg_t		    mask = 1 << wrap->iw_intr;
+	    unsigned long           s;
 
 	    s = pcibr_lock(pcibr_soft);
 	    b_int_enable = bridge->b_int_enable;
@@ -7285,7 +7625,6 @@
 	    pcibr_unlock(pcibr_soft, s);
 	    return;
 	}
-    }
 }
 
 /* =====================================================================
@@ -7403,7 +7742,7 @@
 		bridge->b_pci_err_lower);
     }
     if (int_status & BRIDGE_ISR_ERROR_FATAL) {
-	cmn_err_tag(14, (int)CE_PANIC, "PCI Bridge Error interrupt killed the system");
+	PRINT_PANIC("PCI Bridge Error interrupt killed the system");
 	/*NOTREACHED */
     } else {
 	PRINT_ALERT( "Non-fatal Error in Bridge..");
@@ -7491,10 +7830,8 @@
 				soft->bs_slot[slot].bss_window[win].bssw_base;
 			else if (map->bp_space == PCIIO_SPACE_ROM)
 			    base += pcibr_info->f_rbase;
-#ifdef IRIX
 			if ((pci_addr >= base) && (pci_addr < (base + size)))
-			    atomicAddInt(map->bp_toc, 1);
-#endif
+			    atomic_inc(map->bp_toc);
 		    }
 		}
 	    }
@@ -7532,34 +7869,8 @@
     bridgereg_t             err_status;
     int                     i;
 
-#if defined(SN0_HWDEBUG)
-    extern int		    la_trigger_nasid1;
-    extern int		    la_trigger_nasid2;
-    extern long		    la_trigger_val;
-#endif
-
     /* REFERENCED */
     bridgereg_t             disable_errintr_mask = 0;
-#ifdef IRIX
-    int 		    rv;
-#else
-    int                     rv = 0;
-#endif
-    int 		    error_code = IOECODE_DMA | IOECODE_READ;
-    ioerror_mode_t 	    mode = MODE_DEVERROR;
-    ioerror_t 	            ioe;
-
-#if defined(SN0_HWDEBUG)
-   /*
-    * trigger points for logic analyzer. Used to debug the DMA timeout
-    * note that 0xcafe is added to the trigger values to avoid false
-    * triggers when la_trigger_val shows up in a cacheline as data
-    */
-   if (la_trigger_nasid1 != -1) 
-	REMOTE_HUB_PI_S(la_trigger_nasid1, 0, PI_CPU_NUM, la_trigger_val + 0xcafe);
-   if (la_trigger_nasid2 != -1) 
-	REMOTE_HUB_PI_S(la_trigger_nasid2, 0, PI_CPU_NUM, la_trigger_val + 0xcafe);
-#endif
 
 #if PCIBR_SOFT_LIST
     /* IP27 seems to be handing us junk.
@@ -7635,7 +7946,7 @@
 
 		bs_estat->bs_errcount_total++;
 
-#ifdef IRIX
+#ifdef LATER
 		current_tick = lbolt;
 #else
 		current_tick = 0;
@@ -7777,7 +8088,7 @@
     if ((err_status & BRIDGE_ISR_INVLD_ADDR) &&
 	((((uint64_t) bridge->b_wid_err_upper << 32) | (bridge->b_wid_err_lower))
 	 == (BRIDGE_INT_RST_STAT & 0xff0))) {
-#ifdef IRIX
+#ifdef LATER
 	if (kdebug)
 	    PRINT_NOTICE( "%s bridge: ignoring llp/control address interrupt",
 		    pcibr_soft->bs_name);
@@ -7787,32 +8098,6 @@
     }
 #endif				/* PCIBR_LLP_CONTROL_WAR */
 
-    /* Check if this is the RESP_XTALK_ERROR interrupt. 
-     * This can happen due to a failed DMA READ operation.
-     */
-    if (err_status & BRIDGE_ISR_RESP_XTLK_ERR) {
-	/* Phase 1 : Look at the error state in the bridge and further
-	 * down in the device layers.
-	 */
-#if defined(CONFIG_SGI_IO_ERROR_HANDLING)
-	(void)error_state_set(pcibr_soft->bs_conn, ERROR_STATE_LOOKUP);
-#endif
-	IOERROR_SETVALUE(&ioe, widgetnum, pcibr_soft->bs_xid);
-	(void)pcibr_error_handler((error_handler_arg_t)pcibr_soft,
-				  error_code,
-				  mode,
-				  &ioe);
-	/* Phase 2 : Perform the action agreed upon in phase 1.
-	 */
-#if defined(CONFIG_SGI_IO_ERROR_HANDLING)
-	(void)error_state_set(pcibr_soft->bs_conn, ERROR_STATE_ACTION);
-#endif
-	rv = pcibr_error_handler((error_handler_arg_t)pcibr_soft,
-				 error_code,
-				 mode,
-				 &ioe);
-    }
-    if (rv != IOERROR_HANDLED) {
 #ifdef	DEBUG
 	if (err_status & BRIDGE_ISR_ERROR_DUMP)
 	    pcibr_error_dump(pcibr_soft);
@@ -7822,7 +8107,7 @@
 	    pcibr_error_dump(pcibr_soft);
 	}
 #endif
-    }
+
     /*
      * We can't return without re-enabling the interrupt, since
      * it would cause problems for devices like IOC3 (Lost
@@ -7853,11 +8138,7 @@
 		  iopaddr_t *offsetp,
 		  pciio_function_t *funcp)
 {
-#ifdef IRIX
-    int                     s, f, w;
-#else
     int                     s, f=0, w;
-#endif
     iopaddr_t               base;
     size_t                  size;
     pciio_piospace_t        piosp;
@@ -8082,7 +8363,7 @@
  * decodes the PCI specific portions -- we count on our
  * callers to dump the raw IOE data.
  */
-#ifdef colin
+#ifdef LATER
 #define BEM_ADD_IOE(ioe)						\
 	do {								\
 	    if (IOERROR_FIELDVALID(ioe, busspace)) {			\
@@ -8165,7 +8446,7 @@
      * and need to construct the slot/space/offset.
      */
 
-#ifdef colin
+#ifdef LATER
     bad_xaddr = IOERROR_GETVALUE(ioe, xtalkaddr);
 #else
     bad_xaddr = -1;
@@ -8207,7 +8488,7 @@
 	if (x > 1)
 	    x--;
 	/* x is which devio reg; no guarantee
-	 * pci slot x will be responding.
+	 * PCI slot x will be responding.
 	 * still need to figure out who decodes
 	 * space/offset on the bus.
 	 */
@@ -8253,7 +8534,7 @@
 
     if ((slot == PCIIO_SLOT_NONE) && (space != PCIIO_SPACE_NONE)) {
 	/* we've got a space/offset but not which
-	 * pci slot decodes it. Check through our
+	 * PCI slot decodes it. Check through our
 	 * notions of which devices decode where.
 	 *
 	 * Yes, this "duplicates" some logic in
@@ -8353,9 +8634,7 @@
 		wx = PCIIO_SPACE_MEM;
 	    wl = wb + ws;
 	    if ((wx == raw_space) && (raw_paddr >= wb) && (raw_paddr < wl)) {
-#ifdef IRIX
-		atomicAddInt(map->bp_toc, 1);
-#endif
+		atomic_inc(map->bp_toc);
 		if (slot == PCIIO_SLOT_NONE) {
 		    slot = cs;
 		    space = map->bp_space;
@@ -8369,7 +8648,7 @@
 
     if (space != PCIIO_SPACE_NONE) {
 	if (slot != PCIIO_SLOT_NONE) {
-#ifdef IRIX
+#ifdef LATER
 	    if (func != PCIIO_FUNC_NONE)
 		IOERROR_SETVALUE(ioe, widgetdev, 
 				 pciio_widgetdev_create(slot,func));
@@ -8451,10 +8730,10 @@
      * error interrupt is due to read/write error..
      */
 
-    /* We know the xtalk addr, the raw pci bus space,
-     * the raw pci bus address, the decoded pci bus
+    /* We know the xtalk addr, the raw PCI bus space,
+     * the raw PCI bus address, the decoded PCI bus
      * space, the offset within that space, and the
-     * decoded pci slot (which may be "PCIIO_SLOT_NONE" if no slot
+     * decoded PCI slot (which may be "PCIIO_SLOT_NONE" if no slot
      * is known to be involved).
      */
 
@@ -8506,7 +8785,7 @@
 	    BEM_ADD_VAR(raw_paddr);
 	    if (IOERROR_FIELDVALID(ioe, widgetdev)) {
 
-#ifdef colin
+#ifdef LATER
 		slot = pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe, 
 								 widgetdev));
 		func = pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe, 
@@ -8545,7 +8824,7 @@
 	 *      Need a way to ensure we don't inadvertently clear some
 	 *      other errors.
 	 */
-#ifdef IRIX
+#ifdef LATER
 	if (IOERROR_FIELDVALID(ioe, widgetdev))
 	    pcibr_device_disable(pcibr_soft, 
 				 pciio_widgetdev_slot_get(
@@ -8586,7 +8865,7 @@
      * Look up the address, in the bridge error registers, and
      * take appropriate action
      */
-#ifdef colin
+#ifdef LATER
     ASSERT(IOERROR_GETVALUE(ioe, widgetnum) == pcibr_soft->bs_xid);
     ASSERT(bridge);
 #endif
@@ -8618,7 +8897,7 @@
 
     retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe);
     if (retval != IOERROR_HANDLED)
-#ifdef colin
+#ifdef LATER
 	pcibr_device_disable(pcibr_soft, 
 			     pciio_widgetdev_slot_get(
 				      IOERROR_GETVALUE(ioe,widgetdev)));
@@ -8690,7 +8969,7 @@
 
     retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe);
 
-#ifdef IRIX
+#ifdef LATER
     if (retval != IOERROR_HANDLED) {
 	pcibr_device_disable(pcibr_soft, 
 			     pciio_widgetdev_slot_get(
@@ -8722,22 +9001,8 @@
 {
     pcibr_soft_t            pcibr_soft;
     int                     retval = IOERROR_BADERRORCODE;
-    devfs_handle_t	    xconn_vhdl,pcibr_vhdl;
-#if defined(CONFIG_SGI_IO_ERROR_HANDLING)
-    error_state_t	    e_state;
-#endif
-    pcibr_soft = (pcibr_soft_t) einfo;
-
-    xconn_vhdl = pcibr_soft->bs_conn;
-    pcibr_vhdl = pcibr_soft->bs_vhdl;
 
-#if defined(CONFIG_SGI_IO_ERROR_HANDLING)
-    e_state = error_state_get(xconn_vhdl);
-    
-    if (error_state_set(pcibr_vhdl, e_state) == 
-	ERROR_RETURN_CODE_CANNOT_SET_STATE)
-	return(IOERROR_UNHANDLED);
-#endif
+    pcibr_soft = (pcibr_soft_t) einfo;
 
     /* If we are in the action handling phase clean out the error state
      * on the xswitch.
@@ -8844,7 +9109,7 @@
     bridge_t               *bridge = pcibr_soft->bs_base;
     bridgereg_t             ctlreg;
     unsigned                cfgctl[8];
-    unsigned                s;
+    unsigned long           s;
     int                     f, nf;
     pcibr_info_h            pcibr_infoh;
     pcibr_info_t            pcibr_info;
@@ -8869,11 +9134,7 @@
 	/* XXX delay? */
 
 	for (f = 0; f < nf; ++f)
-#ifdef IRIX
-	    if (pcibr_info = pcibr_infoh[f])
-#else
 	    if ((pcibr_info = pcibr_infoh[f]))
-#endif
 		for (win = 0; win < 6; ++win)
 		    if (pcibr_info->f_window[win].w_base != 0)
 			bridge->b_type0_cfg_dev[pciio_slot].f[f].l[PCI_CFG_BASE_ADDR(win) / 4] =
@@ -8901,7 +9162,7 @@
     pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
     bridgereg_t             devreg;
-    unsigned                s;
+    unsigned long           s;
 
     /*
      * Bridge supports hardware swapping; so we can always
@@ -8944,7 +9205,7 @@
 			pciio_slot_t pciio_slot,
 			pciio_priority_t device_prio)
 {
-    int                     s;
+    unsigned long           s;
     int                    *counter;
     bridgereg_t             rtbits = 0;
     bridgereg_t             devreg;
@@ -8966,9 +9227,9 @@
      * XXX- Bug in Rev B Bridge Si:
      * Symptom: Prefetcher starts operating incorrectly. This happens
      * due to corruption of the address storage ram in the prefetcher
-     * when a non-real time pci request is pulled and a real-time one is
+     * when a non-real time PCI request is pulled and a real-time one is
      * put in it's place. Workaround: Use only a single arbitration ring
-     * on pci bus. GBR and RR can still be uniquely used per
+     * on PCI bus. GBR and RR can still be uniquely used per
      * device. NETLIST MERGE DONE, WILL BE FIXED IN REV C.
      */
 
@@ -8983,18 +9244,12 @@
     s = pcibr_lock(pcibr_soft);
     devreg = pcibr_soft->bs_slot[pciio_slot].bss_device;
     if (device_prio == PCI_PRIO_HIGH) {
-#ifdef IRIX
-	if (++*counter == 1)
-#else
 	if ((++*counter == 1)) {
-#endif
 	    if (rtbits)
 		devreg |= rtbits;
 	    else
 		rc = PRIO_FAIL;
-#ifndef IRIX
 	}
-#endif
     } else if (device_prio == PCI_PRIO_LOW) {
 	if (*counter <= 0)
 	    rc = PRIO_FAIL;
@@ -9082,15 +9337,11 @@
 
     if (set || clr) {
 	bridgereg_t             devreg;
-	unsigned                s;
+	unsigned long           s;
 
 	s = pcibr_lock(pcibr_soft);
 	devreg = pcibr_soft->bs_slot[pciio_slot].bss_device;
-#ifdef IRIX
-	devreg = devreg & ~clr | set;
-#else
 	devreg = (devreg & ~clr) | set;
-#endif
 	if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) {
 	    bridge_t               *bridge = pcibr_soft->bs_base;
 
@@ -9146,13 +9397,9 @@
 
     pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast;
 
-    if ( (pcibr_soft_t)0 != pcibr_soft ) {
-	bridge = pcibr_soft->bs_base;
-	if ( (bridge_t *)0 != bridge ) {
-		cfgbase = bridge->b_type0_cfg_dev[pciio_slot].f[pciio_func].l;
-	}
-    }
+    bridge = pcibr_soft->bs_base;
 
+    cfgbase = bridge->b_type0_cfg_dev[pciio_slot].f[pciio_func].l;
 
     return cfgbase;
 }
@@ -9215,7 +9462,7 @@
     case 3:
 	if (reg & 1) {
 	    CB(cfgbase, reg) = value;
-	    CS(cfgbase, reg + 1) = value >> 8;
+	    CS(cfgbase, (reg + 1)) = value >> 8;
 	} else {
 	    CS(cfgbase, reg) = value;
 	    CB(cfgbase, reg + 2) = value >> 16;
@@ -9266,6 +9513,16 @@
 
     (pciio_error_devenable_f *) pcibr_error_devenable,
     (pciio_error_extract_f *) pcibr_error_extract,
+
+#ifdef LATER
+    (pciio_driver_reg_callback_f *) pcibr_driver_reg_callback,
+    (pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback,
+#else
+    (pciio_driver_reg_callback_f *) 0,
+    (pciio_driver_unreg_callback_f *) 0,
+#endif
+    (pciio_device_unregister_f 	*) pcibr_device_unregister,
+    (pciio_dma_enabled_f		*) pcibr_dma_enabled,
 };
 
 LOCAL                   pcibr_hints_t
@@ -9299,7 +9556,7 @@
     return (pcibr_hints_t) ainfo;
 
 abnormal_exit:
-#ifdef IRIX
+#ifdef LATER
     printf("SHOULD NOT BE HERE\n");
 #endif
     DEL(hint);
@@ -9417,12 +9674,7 @@
 	if (ainfo == (arbitrary_info_t) subdevp)
 	    return;
 	DEL(subdevp);
-#ifdef IRIX
-	if (ainfo == NULL)
-#else
-	if (ainfo == (arbitrary_info_t) NULL)
-#endif
-	{
+	if (ainfo == (arbitrary_info_t) NULL) {
 #if DEBUG
 	    printk("pcibr_hints_subdevs: null subdevs ptr at\n"
 		    "\t%p\n", pconn_vhdl);
@@ -9438,7 +9690,7 @@
 }
 
 
-#ifdef colin
+#ifdef LATER
 
 #include <sys/idbg.h>
 #include <sys/idbgentry.h>
@@ -9531,7 +9783,7 @@
 	    pss->bss_d32_base, pss->bss_d32_flags);
     
     qprintf("\tExt ATEs active ? %s", 
-	    pss->bss_ext_ates_active ? "yes" : "no");
+	    atomic_read(&pss->bss_ext_ates_active) ? "yes" : "no");
     qprintf(" Command register : 0x%x ", pss->bss_cmd_pointer);
     qprintf(" Shadow command val : 0x%x\n", pss->bss_cmd_shadow);
 
@@ -9559,7 +9811,7 @@
 	qprintf("Invalid ips %d\n",ips);
 }
 
-#endif /* colin */
+#endif /* LATER */
 
 int
 pcibr_dma_enabled(devfs_handle_t pconn_vhdl)
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/pciio.c linux/arch/ia64/sn/io/pciio.c
--- v2.4.3/linux/arch/ia64/sn/io/pciio.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/pciio.c	Thu Apr  5 12:51:47 2001
@@ -14,6 +14,7 @@
 #include <linux/config.h>
 #include <linux/slab.h>
 #include <asm/sn/sgi.h>
+#include <asm/sn/xtalk/xbow.h>	/* Must be before iograph.h to get MAX_PORT_NUM */
 #include <asm/sn/iograph.h>
 #include <asm/sn/invent.h>
 #include <asm/sn/hcl.h>
@@ -23,6 +24,7 @@
 #include <asm/sn/ioerror_handling.h>
 #include <asm/sn/pci/pciio.h>
 #include <asm/sn/pci/pciio_private.h>
+#include <asm/sn/sn_sal.h>
 
 #define DEBUG_PCIIO
 #undef DEBUG_PCIIO	/* turn this on for yet more console output */
@@ -38,28 +40,30 @@
 int
 badaddr_val(volatile void *addr, int len, volatile void *ptr)
 {
+	int ret = 0;
+	volatile void *new_addr;
+
 	switch (len) {
-		case 4: *(volatile u32*)ptr = *(((volatile u32*)(((u64) addr)^4)));
-		default: printk("FIXME: argh fix badaddr_val\n");
+		case 4:
+			new_addr = (void *)(((u64) addr)^4);
+			ret = ia64_sn_probe_io_slot((long)new_addr, len, (void *)ptr);
+			break;
+		default:
+			printk(KERN_WARNING "badaddr_val given len %x but supports len of 4 only\n", len);
 	}
-	/* no such thing as a bad addr .... */
-	return(0);
-}
 
+	if (ret < 0)
+		panic("badaddr_val: unexpected status (%d) in probing", ret);
+	return(ret);
 
-void
-cmn_err_tag(int seqnumber, register int level, char *fmt, ...)
-{
 }
 
+
 nasid_t
 get_console_nasid(void)
 {
-#ifdef IRIX
+	extern nasid_t console_nasid;
 	return console_nasid;
-#else
-	return 0;
-#endif
 }
 
 int
@@ -208,8 +212,8 @@
 void			pciio_device_info_free(pciio_info_t);
 devfs_handle_t		pciio_device_info_register(devfs_handle_t, pciio_info_t);
 void			pciio_device_info_unregister(devfs_handle_t, pciio_info_t);
-int                     pciio_device_attach(devfs_handle_t);
-int			pciio_device_detach(devfs_handle_t);
+int                     pciio_device_attach(devfs_handle_t, int);
+int			pciio_device_detach(devfs_handle_t, int);
 void                    pciio_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_t);
 
 int                     pciio_reset(devfs_handle_t);
@@ -234,13 +238,30 @@
     pciio_info_t            card_info;
     pciio_provider_t       *provider_fns;
 
-    card_info = pciio_info_get(dev);
-    ASSERT(card_info != NULL);
+    /*
+     * We're called with two types of vertices, one is
+     * the bridge vertex (ends with "pci") and the other is the
+     * pci slot vertex (ends with "pci/[0-8]").  For the first type
+     * we need to get the provider from the PFUNCS label.  For
+     * the second we get it from fastinfo/c_pops.
+     */
+    provider_fns = pciio_provider_fns_get(dev);
+    if (provider_fns == NULL) {
+	card_info = pciio_info_get(dev);
+	if (card_info != NULL) {
+		provider_fns = pciio_info_pops_get(card_info);
+	}
+    }
+
+    if (provider_fns == NULL)
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+	PRINT_PANIC("%v: provider_fns == NULL", dev);
+#else
+	PRINT_PANIC("0x%x: provider_fns == NULL", dev);
+#endif
 
-    provider_fns = pciio_info_pops_get(card_info);
-    ASSERT(provider_fns != NULL);
+    return provider_fns;
 
-    return (provider_fns);
 }
 
 #define DEV_FUNC(dev,func)	pciio_to_provider_fns(dev)->func
@@ -672,15 +693,21 @@
     error_state_t	    e_state;
 #endif
 
-#ifdef IRIX
 #if DEBUG && ERROR_DEBUG
-    cmn_err(CE_CONT, "%v: pciio_error_handler\n", pciio_vhdl);
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk("%v: pciio_error_handler\n", pciio_vhdl);
+#else
+    printk("0x%x: pciio_error_handler\n", pciio_vhdl);
 #endif
 #endif
 
-    IOERR_PRINTF(cmn_err(CE_NOTE,
-			 "%v: PCI Bus Error: Error code: %d Error mode: %d\n",
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    IOERR_PRINTF(printk("%v: PCI Bus Error: Error code: %d Error mode: %d\n",
 			 pciio_vhdl, error_code, mode));
+#else
+    IOERR_PRINTF(printk("0x%x: PCI Bus Error: Error code: %d Error mode: %d\n",
+			 pciio_vhdl, error_code, mode));
+#endif
 
     /* If there is an error handler sitting on
      * the "no-slot" connection point, give it
@@ -715,7 +742,7 @@
 	 * widgetdev is a 4byte value encoded as slot in the higher order
 	 * 2 bytes and function in the lower order 2 bytes.
 	 */
-#ifdef IRIX
+#ifdef LATER
 	slot = pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioerror, widgetdev));
 #else
 	slot = 0;
@@ -732,9 +759,12 @@
 #if defined(CONFIG_SGI_IO_ERROR_HANDLING)
 		e_state = error_state_get(pciio_vhdl);
 
+
 		if (e_state == ERROR_STATE_ACTION)
 		    (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE);
 
+
+
 		if (error_state_set(pconn_vhdl,e_state) ==
 		    ERROR_RETURN_CODE_CANNOT_SET_STATE)
 		    return(IOERROR_UNHANDLED);
@@ -825,12 +855,18 @@
     ASSERT((desired_end == PCIDMA_ENDIAN_BIG) || (desired_end == PCIDMA_ENDIAN_LITTLE));
 
 #if DEBUG
-    cmn_err(CE_ALERT,
-	    "%v: pciio_endian_set is going away.\n"
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    PRINT_ALERT("%v: pciio_endian_set is going away.\n"
+	    "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n"
+	    "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n",
+	    dev);
+#else
+    PRINT_ALERT("0x%x: pciio_endian_set is going away.\n"
 	    "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n"
 	    "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n",
 	    dev);
 #endif
+#endif
 
     return DEV_FUNC(dev, endian_set)
 	(dev, device_end, desired_end);
@@ -1027,8 +1063,6 @@
 	(pciio_info->c_fingerprint != pciio_info_fingerprint)) {
 #endif /* BRINGUP */
 
-	printk("pciio_info_get: Found fastinfo 0x%p but wrong fingerprint %s\n", pciio_info,
-	pciio_info->c_fingerprint);
 	return((pciio_info_t)-1); /* Should panic .. */
     }
 	
@@ -1198,7 +1232,11 @@
 pciio_attach(devfs_handle_t pciio)
 {
 #if DEBUG && ATTACH_DEBUG
-    cmn_err(CE_CONT, "%v: pciio_attach\n", pciio);
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk("%v: pciio_attach\n", pciio);
+#else
+    printk("0x%x: pciio_attach\n", pciio);
+#endif
 #endif
     return 0;
 }
@@ -1220,11 +1258,7 @@
 {
     arbitrary_info_t        ainfo;
 
-#ifdef IRIX
-    hwgraph_info_remove_LBL(provider, INFO_LBL_PFUNCS, &ainfo);
-#else
     hwgraph_info_remove_LBL(provider, INFO_LBL_PFUNCS, (long *) &ainfo);
-#endif
 }
 
 /*
@@ -1258,7 +1292,7 @@
 
     return cdl_add_driver(pciio_registry,
 			  vendor_id, device_id,
-			  driver_prefix, flags);
+			  driver_prefix, flags, NULL);
 }
 
 /*
@@ -1274,7 +1308,33 @@
      */
     ASSERT(pciio_registry != NULL);
 
-    cdl_del_driver(pciio_registry, driver_prefix);
+    cdl_del_driver(pciio_registry, driver_prefix, NULL);
+}
+
+/* 
+ * Set the slot status for a device supported by the 
+ * driver being registered.
+ */
+void
+pciio_driver_reg_callback(
+                           devfs_handle_t pconn_vhdl,
+			   int key1,
+			   int key2,
+                           int error)
+{
+}
+
+/* 
+ * Set the slot status for a device supported by the 
+ * driver being unregistered.
+ */
+void
+pciio_driver_unreg_callback(
+                           devfs_handle_t pconn_vhdl,
+			   int key1,
+			   int key2,
+                           int error)
+{
 }
 
 /*
@@ -1307,7 +1367,6 @@
 		pciio_vendor_id_t vendor_id,
 		pciio_device_id_t device_id)
 {
-
     return pciio_device_info_register
 	(connectpt, pciio_device_info_new (NULL, master, slot, func,
 					   vendor_id, device_id));
@@ -1366,8 +1425,6 @@
 			    pciio_info->c_slot,
 			    pciio_info->c_func);
 
-    printk("pciio_device_info_register: connectpt 0x%p, pciio_info 0x%p\n", connectpt, pciio_info);
-
     if (GRAPH_SUCCESS !=
 	hwgraph_path_add(connectpt, name, &pconn))
 	return pconn;
@@ -1379,7 +1436,9 @@
 	int pos;
 	char dname[256];
 	pos = devfs_generate_path(pconn, dname, 256);
+#ifdef DEBUG_PCIIO
 	printk("%s : pconn path= %s \n", __FUNCTION__, &dname[pos]);
+#endif
     }
 #endif /* BRINGUP */
 
@@ -1421,6 +1480,7 @@
     /* Remove the link to our pci provider */
     hwgraph_edge_remove(pconn, EDGE_LBL_MASTER, NULL);
 
+
     hwgraph_vertex_unref(pconn);
     hwgraph_vertex_destroy(pconn);
     
@@ -1447,18 +1507,21 @@
 static void
 pciio_device_inventory_remove(devfs_handle_t pconn_vhdl)
 {
-#ifdef IRIX
+#ifdef LATER
     hwgraph_inventory_remove(pconn_vhdl,-1,-1,-1,-1,-1);
 #endif
 }
 
 /*ARGSUSED */
 int
-pciio_device_attach(devfs_handle_t pconn)
+pciio_device_attach(devfs_handle_t pconn,
+		    int          drv_flags)
 {
     pciio_info_t            pciio_info;
     pciio_vendor_id_t       vendor_id;
     pciio_device_id_t       device_id;
+    int pciba_attach(devfs_handle_t);
+
 
     pciio_device_inventory_add(pconn);
     pciio_info = pciio_info_get(pconn);
@@ -1466,8 +1529,6 @@
     vendor_id = pciio_info->c_vendor;
     device_id = pciio_info->c_device;
 
-    printk("pciio_device_attach: Function 0x%p, vendor 0x%x, device_id %x\n", pconn, vendor_id, device_id);
-
     /* we don't start attaching things until
      * all the driver init routines (including
      * pciio_init) have been called; so we
@@ -1475,12 +1536,17 @@
      */
     ASSERT(pciio_registry != NULL);
 
-    return(cdl_add_connpt(pciio_registry, vendor_id, device_id, pconn));
+    /*
+     * Since pciba is not called from cdl routines .. call it here.
+     */
+    pciba_attach(pconn);
 
+    return(cdl_add_connpt(pciio_registry, vendor_id, device_id, pconn, drv_flags));
 }
 
 int
-pciio_device_detach(devfs_handle_t pconn)
+pciio_device_detach(devfs_handle_t pconn,
+		    int          drv_flags)
 {
     pciio_info_t            pciio_info;
     pciio_vendor_id_t       vendor_id;
@@ -1499,10 +1565,9 @@
      */
     ASSERT(pciio_registry != NULL);
 
-    cdl_del_connpt(pciio_registry, vendor_id, device_id, pconn);
+    return(cdl_del_connpt(pciio_registry, vendor_id, device_id,
+		          pconn, drv_flags));
 
-    return(0);
-    
 }
 
 /*
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/sgi_if.c linux/arch/ia64/sn/io/sgi_if.c
--- v2.4.3/linux/arch/ia64/sn/io/sgi_if.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/sgi_if.c	Thu Apr  5 12:51:47 2001
@@ -21,8 +21,6 @@
 #include <asm/sn/pci/pciio.h>
 #include <asm/sn/slotnum.h>
 
-#define spinlock_init(x,name) mutex_init(x, MUTEX_DEFAULT, name);
-
 void *
 kmem_zalloc(size_t size, int flag)
 {
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/sgi_io_init.c linux/arch/ia64/sn/io/sgi_io_init.c
--- v2.4.3/linux/arch/ia64/sn/io/sgi_io_init.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/sgi_io_init.c	Thu Apr  5 12:51:47 2001
@@ -79,13 +79,8 @@
 void
 sgi_master_io_infr_init(void)
 {
-#ifdef Colin
-	/*
-	 * Simulate Big Window 0.
-	 * Only when we build for lutsen etc. ..
-	 */
-	simulated_BW0_init();
-#endif
+	int cnode;
+	extern int maxnodes;
 
 	/*
 	 * Do any early init stuff .. einit_tbl[] etc.
@@ -122,7 +117,9 @@
 	sn_mp_setup();
 
 	DBG("--> sgi_master_io_infr_init: calling per_hub_init(0).\n");
-	per_hub_init(0); /* Need to get and send in actual cnode number */
+	for (cnode = 0; cnode < maxnodes; cnode++) {
+		per_hub_init(cnode);
+	}
 
 	/* We can do headless hub cnodes here .. */
 
@@ -188,7 +185,7 @@
 	/* Emulate cboot() .. */
 	mlreset(1); /* This is a slave cpu */
 
-	per_hub_init(0); /* Need to get and send in actual cnode number */
+	// per_hub_init(0); /* Need to get and send in actual cnode number */
 
 	/* Done */
 }
@@ -212,12 +209,8 @@
 	 * do not currently support yet .. just a hack for now.
 	 */
 #ifdef NUMA_BASE
-	DBG("sn_mp_setup(): maxnodes= %d  numnodes= %d\n", maxnodes,numnodes);
         maxnodes = numnodes;
-#ifdef SIMULATED_KLGRAPH
-	maxnodes = 1;
-	numnodes = 1;
-#endif /* SIMULATED_KLGRAPH */
+	DBG("sn_mp_setup(): maxnodes= %d  numnodes= %d\n", maxnodes,numnodes);
         printk("sn_mp_setup(): Allocating backing store for *Nodepdaindr[%2d] \n",
                 maxnodes);
 
@@ -259,6 +252,14 @@
 	 *      ml/SN/promif.c
 	 */
 
+#ifdef CONFIG_IA64_SGI_SN1
+	for (cpu = 0; cpu < smp_num_cpus; cpu++) {
+		/* Skip holes in CPU space */
+		if (cpu_enabled(cpu)) {
+			init_platform_pda(cpu);
+		}
+	}
+#endif
 	for (cnode = 0; cnode < maxnodes; cnode++) {
 		/*
 		 * Set up platform-dependent nodepda fields.
@@ -267,29 +268,7 @@
 		 */
 		DBG("sn_mp_io_setup: calling init_platform_nodepda(%2d)\n",cnode);
 		init_platform_nodepda(Nodepdaindr[cnode], cnode);
-
-		/*
-		 * This routine clears the Hub's Interrupt registers.
-		 */
-#ifndef CONFIG_IA64_SGI_IO
-		/*
-		 * We need to move this intr_clear_all() routine 
-		 * from SN/intr.c to a more appropriate file.
-		 * Talk to Al Mayer.
-		 */
-                intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
-#endif
 	}
-
-#ifdef CONFIG_IA64_SGI_IO
-	for (cpu = 0; cpu < smp_num_cpus; cpu++) {
-		/* Skip holes in CPU space */
-		if (cpu_enabled(cpu)) {
-			init_platform_pda(cpu);
-		}
-	}
-#endif
-
 	/*
 	 * Initialize platform-dependent vertices in the hwgraph:
 	 *	module
@@ -309,4 +288,26 @@
 	klhwg_add_all_modules(hwgraph_root);
 	DBG("sn_mp_setup: calling klhwg_add_all_nodes()\n");
 	klhwg_add_all_nodes(hwgraph_root);
+
+
+	for (cnode = 0; cnode < maxnodes; cnode++) {
+
+		/*
+		 * This routine clears the Hub's Interrupt registers.
+		 */
+#ifdef CONFIG_IA64_SGI_SN1
+		/*
+		 * We need to move this intr_clear_all() routine 
+		 * from SN/intr.c to a more appropriate file.
+		 * Talk to Al Mayer.
+		 */
+                intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
+		/* now init the hub */
+	//	per_hub_init(cnode);
+#endif
+	}
+
+#if defined(CONFIG_IA64_SGI_SYNERGY_PERF)
+	synergy_perf_init();
+#endif /* CONFIG_IA64_SGI_SYNERGY_PERF */
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/sgi_io_sim.c linux/arch/ia64/sn/io/sgi_io_sim.c
--- v2.4.3/linux/arch/ia64/sn/io/sgi_io_sim.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/sgi_io_sim.c	Thu Apr  5 12:51:47 2001
@@ -17,9 +17,6 @@
 #include <asm/sn/sn_private.h>
 #include <asm/sn/synergy.h>
 
-cnodeid_t nasid_to_compact_node[MAX_NASIDS];
-nasid_t compact_to_nasid_node[MAX_COMPACT_NODES];
-cnodeid_t cpuid_to_compact_node[MAXCPUS];
 cpuid_t         master_procid = 0;
 int maxnodes;
 char arg_maxnodes[4];
@@ -42,12 +39,6 @@
         return (strlen(s) != 0);
 }
 
-
-void pciba_init(void)
-{
-	FIXME("pciba_init : no-op\n");
-}
-
 void xbmon_init(void)
 {
 	FIXME("xbmon_init : no-op\n");
@@ -82,7 +73,7 @@
  * Routines provided by ml/SN/promif.c.
  */
 static __psunsigned_t master_bridge_base = (__psunsigned_t)NULL;
-static nasid_t console_nasid;
+nasid_t console_nasid;
 static char console_wid;
 static char console_pcislot;
 
@@ -90,19 +81,12 @@
 set_master_bridge_base(void)
 {
 
-#ifdef SIMULATED_KLGRAPH
-	printk("set_master_bridge_base: SIMULATED_KLGRAPH FIXME hardwired master.\n");
-	console_nasid = 0;
-	console_wid = 0x8;
-	console_pcislot = 0x2;
-#else
         console_nasid = KL_CONFIG_CH_CONS_INFO(master_nasid)->nasid;
         console_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base);
         console_pcislot = KL_CONFIG_CH_CONS_INFO(master_nasid)->npci;
-#endif /* SIMULATED_KLGRAPH */
-
         master_bridge_base = (__psunsigned_t)NODE_SWIN_BASE(console_nasid,
                                                             console_wid);
+	FIXME("WARNING: set_master_bridge_base: NON NASID 0 DOES NOT WORK\n");
 }
 
 int
@@ -133,21 +117,6 @@
         } else {
                 return 0;
         }
-}
-
-cnodeid_t
-nasid_to_compact_nodeid(nasid_t nasid)
-{
-        ASSERT(nasid >= 0 && nasid < MAX_NASIDS);
-        return nasid_to_compact_node[nasid];
-}
-
-nasid_t
-compact_to_nasid_nodeid(cnodeid_t cnode)
-{
-        ASSERT(cnode >= 0 && cnode <= MAX_COMPACT_NODES);
-        ASSERT(compact_to_nasid_node[cnode] >= 0);
-        return compact_to_nasid_node[cnode];
 }
 
 /*
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/stubs.c linux/arch/ia64/sn/io/stubs.c
--- v2.4.3/linux/arch/ia64/sn/io/stubs.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/stubs.c	Thu Apr  5 12:51:47 2001
@@ -31,8 +31,6 @@
 int force_fire_and_forget;
 int ignore_conveyor_override;
 
-#define spinlock_init(x,name) mutex_init(x, MUTEX_DEFAULT, name);
-
 devfs_handle_t dummy_vrtx;	/* Needed for cpuid_to_vertex() in hack.h */
 
 
@@ -105,32 +103,6 @@
 	return((zone_t *)0);
 }
 
-uint64_t
-rmalloc(struct map *mp, size_t size)
-{
-	FIXME("rmalloc : returns NULL");
-	return((uint64_t)0);
-}
-
-void
-rmfree(struct map *mp, size_t size, uint64_t a)
-{
-	FIXME("rmfree : no-op");
-}
-
-struct map *
-rmallocmap(uint64_t mapsiz)
-{
-	FIXME("rmallocmap : returns NULL");
-	return((struct map *)0);
-}
-
-void
-rmfreemap(struct map *mp)
-{
-	FIXME("rmfreemap : no-op");
-}
-
 int
 compare_and_swap_ptr(void **location, void *old_ptr, void *new_ptr)
 {
@@ -170,40 +142,6 @@
 ioc3_console_vhdl_get(void)
 	{FIXME("ioc3_console_vhdl_get"); return( (devfs_handle_t)-1);}
 
-
-#if 0
-#define io_splock(l) 1
-#define io_spunlock(l,s)
-
-#define spinlock_destroy(a)     /* needed by pcibr_detach() */
-#define mutex_spinlock(a) 0
-#define mutex_spinunlock(a,b)
-#define mutex_init(a,b,c)               ;
-#define mutex_lock(a,b)                 ;
-#define mutex_unlock(a)                 ;
-#define dev_to_vhdl(dev) 0
-#define get_timestamp() 0
-#define us_delay(a)
-#define v_mapphys(a,b,c) 0
-#define splhi()  0
-#define splx(s)
-#define spinlock_init(x,name) mutex_init(x, MUTEX_DEFAULT, name);
-#endif /* 0 */
-
-int
-cap_able(uint64_t x)
-{
-	FIXME("cap_able : returns 1");
-	return(1);
-}
-
-int
-cap_able_cred(uint64_t a, uint64_t b)
-{
-	FIXME("cap_able_cred : returns 1");
-	return(1);
-}
-
 void
 nic_vmc_check(devfs_handle_t vhdl, char *nicinfo)
 {
@@ -236,21 +174,5 @@
               uint64_t value)
 {
 	FIXME("vector_write_node\n");
-	return(0);
-}
-
-int
-atomicAddInt(int *int_ptr, int value)
-{
-//	FIXME("atomicAddInt : simple add\n");
-	*int_ptr += value;
-	return(0);
-}
-
-int
-atomicClearInt(int *int_ptr, int value)
-{
-	FIXME("atomicClearInt : simple clear\n");
-	*int_ptr &= ~value;
 	return(0);
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/xbow.c linux/arch/ia64/sn/io/xbow.c
--- v2.4.3/linux/arch/ia64/sn/io/xbow.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/ia64/sn/io/xbow.c	Thu Apr 12 12:16:35 2001
@@ -9,7 +9,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <asm/sn/sgi.h>
@@ -17,19 +16,18 @@
 #include <asm/sn/invent.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
+#include <asm/sn/hack.h>
 #include <asm/sn/pci/bridge.h>
 #include <asm/sn/xtalk/xtalk_private.h>
 
-#define DEBUG		1
-#define XBOW_DEBUG	1
+/* #define DEBUG		1 */
+/* #define XBOW_DEBUG	1 */
 
 
 /*
  * Files needed to get the device driver entry points
  */
 
-/* #include <asm/cred.h> */
-
 #include <asm/sn/xtalk/xbow.h>
 #include <asm/sn/xtalk/xtalk.h>
 #include <asm/sn/xtalk/xswitch.h>
@@ -66,7 +64,7 @@
     xbow_perf_t             xbow_perfcnt[XBOW_PERF_COUNTERS];
     xbow_perf_link_t        xbow_perflink[MAX_XBOW_PORTS];
     xbow_link_status_t      xbow_link_status[MAX_XBOW_PORTS];
-    lock_t                  xbow_perf_lock;
+    spinlock_t              xbow_perf_lock;
     int                     link_monitor;
     widget_cfg_t	   *wpio[MAX_XBOW_PORTS];	/* cached PIO pointer */
 
@@ -74,7 +72,7 @@
      * destination port since contention happens there.
      * Implicit mapping from xbow ports (8..f) -> (0..7) array indices.
      */
-    lock_t		    xbow_bw_alloc_lock;		/* bw allocation lock */
+    spinlock_t		    xbow_bw_alloc_lock;		/* bw allocation lock */
     unsigned long long	    bw_hiwm[MAX_XBOW_PORTS];	/* hiwater mark values */
     unsigned long long      bw_cur_used[MAX_XBOW_PORTS]; /* bw used currently */
 };
@@ -118,15 +116,8 @@
 
 int                     xbow_disable_llp_monitor(devfs_handle_t);
 int                     xbow_enable_llp_monitor(devfs_handle_t);
-
-#ifdef IRIX
-int			xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t,
-				unsigned long long, unsigned long long);
-#else
 int                     xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t,
                                 unsigned long long, unsigned long long);
-#endif
-
 
 xswitch_reset_link_f    xbow_reset_link;
 
@@ -237,7 +228,11 @@
     int			    xbow_num;
 	
 #if DEBUG && ATTACH_DEBUG
-    cmn_err(CE_CONT, "%v: xbow_attach\n", conn);
+#if defined(SUPPORT_PRINTING_V_FORMAT
+    printk("%v: xbow_attach\n", conn);
+#else
+    printk("0x%x: xbow_attach\n", conn);
+#endif
 #endif
 
     /*
@@ -261,7 +256,9 @@
      * of our connection point.
      */
     busv = hwgraph_connectpt_get(conn);
+#if DEBUG && ATTACH_DEBUG
     printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%x\n", busv, conn, xbow, *(volatile u32 *)xbow);
+#endif
 
     ASSERT(busv != GRAPH_VERTEX_NONE);
 
@@ -283,8 +280,7 @@
                         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
                         /* &hcl_fops */ (void *)&vhdl, NULL);
     if (!vhdl) {
-        printk("xbow_attach: Unable to create char device for xbow conn
-0x%p\n",
+        printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %p\n",
                 conn);
     }
 
@@ -306,11 +302,7 @@
     /* Add xbow number as a suffix to the hwgraph name of the xbow.
      * This is helpful while looking at the error/warning messages.
      */
-#if CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC
     xbow_num = 0;
-#else
-    xbow_num = xswitch_id_get(busv);
-#endif
 
     /*
      * get the name of this xbow vertex and keep the info.
@@ -341,7 +333,7 @@
      * Crossbow is DOWNREV: these chips are not good
      * to have around, and the operator should be told.
      */
-#ifdef IRIX
+#ifdef	LATER
 #if !DEBUG
     if (
 #if SHOW_REVS
@@ -349,8 +341,7 @@
 #endif	/* SHOW_REVS */
 	   (rev < XBOW_REV_1_1))
 #endif	/* !DEBUG  */
-	cmn_err((rev < XBOW_REV_1_1) ? CE_WARN : CE_CONT,
-		"%sCrossbow ASIC: rev %s (code=%d) at %s%s",
+	printk("%sCrossbow ASIC: rev %s (code=%d) at %s%s",
 		(rev < XBOW_REV_1_1) ? "DOWNREV " : "",
 		(rev == XBOW_REV_1_0) ? "1.0" :
 		(rev == XBOW_REV_1_1) ? "1.1" :
@@ -362,14 +353,13 @@
 		"unknown",
 		rev, soft->name,
 		(rev < XBOW_REV_1_1) ? "" : "\n");
-#endif	/* IRIX */
-
-    spinlock_init(&soft->xbow_perf_lock, "xbow_perf_lock");
+#endif	/* LATER */
+    mutex_spinlock_init(&soft->xbow_perf_lock);
     soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a;
     soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b;
 
     /* Initialization for GBR bw allocation */
-    spinlock_init(&soft->xbow_bw_alloc_lock, "xbow_bw_alloc_lock");
+    mutex_spinlock_init(&soft->xbow_bw_alloc_lock);
 
 #define	XBOW_8_BIT_PORT_BW_MAX		(400 * 1000 * 1000)	/* 400 MB/s */
 #define XBOW_16_BIT_PORT_BW_MAX		(800 * 1000 * 1000)	/* 800 MB/s */
@@ -403,7 +393,7 @@
     xwidget_error_register(conn, xbow_error_handler, soft);
 
 #else
-    printk("xbow_attach: Fixme: we bypassed attaching xbow error interrupt.\n");
+    FIXME("xbow_attach: Fixme: we bypassed attaching xbow error interrupt.\n");
 #endif /* LATER */
 
     /*
@@ -479,8 +469,6 @@
 int
 xbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp)
 {
-    if (!_CAP_CRABLE((uint64_t)credp, CAP_DEVICE_MGT))
-	return EPERM;
     return 0;
 
 }
@@ -525,28 +513,9 @@
 	char		devname[MAXDEVNAME];
 	xwidget_info_t	xwidget_info;
 	int		i;
-#if IP27
-	cnodeid_t	cnodeid = CNODEID_NONE;
-#endif
 
 	vertex_to_name(dev, devname, MAXDEVNAME);
 
-#if IP30
-	/* If there is a ".connection" edge from this vertex,
-	 * then it must be "/hw/node" vertex. Return the widget
-	 * number for heart: 8.
-	 */
-	if (hwgraph_edge_get(dev, EDGE_LBL_CONN, &tdev) ==
-			GRAPH_SUCCESS) {
-		return ((xwidgetnum_t) 8);
-	}
-#elif IP27
-	if ((cnodeid = nodevertex_to_cnodeid(dev)) != CNODEID_NONE) {
-		ASSERT(cnodeid < maxnodes);
-		return(hub_widget_id(COMPACT_TO_NASID_NODEID(cnodeid)));
-	}
-#endif
-
 	/* If this is a pci controller vertex, traverse up using
 	 * the ".." links to get to the widget.
 	 */
@@ -601,7 +570,7 @@
     ASSERT_ALWAYS(rc != 0);
 #endif
     switch (cmd) {
-#ifdef IRIX
+#ifdef LATER
     case XBOWIOC_PERF_ENABLE:
     case XBOWIOC_PERF_DISABLE:
 	{
@@ -630,7 +599,7 @@
 	}
 #endif
 
-#ifdef IRIX
+#ifdef LATER
     case XBOWIOC_PERF_GET:
 	{
 	    xbow_perf_link_t       *xbow_perf_cnt;
@@ -652,10 +621,6 @@
 #endif
 
     case XBOWIOC_LLP_ERROR_ENABLE:
-	if (!_CAP_CRABLE((uint64_t)cr, CAP_DEVICE_MGT)) {
-	    error = EPERM;
-	    break;
-	}
 	if ((error = xbow_enable_llp_monitor(vhdl)) != 0)
 	    error = EINVAL;
 
@@ -663,16 +628,12 @@
 
     case XBOWIOC_LLP_ERROR_DISABLE:
 
-	if (!_CAP_CRABLE((uint64_t)cr, CAP_DEVICE_MGT)) {
-	    error = EPERM;
-	    break;
-	}
 	if ((error = xbow_disable_llp_monitor(vhdl)) != 0)
 	    error = EINVAL;
 
 	break;
 
-#ifdef IRIX
+#ifdef LATER
     case XBOWIOC_LLP_ERROR_GET:
 	{
 	    xbow_link_status_t     *xbow_llp_status;
@@ -693,17 +654,12 @@
 	}
 #endif
 
-#ifdef IRIX
+#ifdef LATER
     case GIOCSETBW:
 	{
 	    grio_ioctl_info_t info;
 	    xwidgetnum_t src_widgetnum, dest_widgetnum;
 
-	    if (!cap_able(CAP_DEVICE_MGT)) {
-		error = EPERM;
-		break;
-	    }
-
 	    if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) {
 		error = EFAULT;
 		break;
@@ -863,14 +819,14 @@
     xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);
 }
 
-#define	XEM_ADD_STR(s)		cmn_err(CE_CONT, "%s", (s))
-#define	XEM_ADD_NVAR(n,v)	cmn_err(CE_CONT, "\t%20s: 0x%x\n", (n), (v))
+#define	XEM_ADD_STR(s)		printk("%s", (s))
+#define	XEM_ADD_NVAR(n,v)	printk("\t%20s: 0x%x\n", (n), (v))
 #define	XEM_ADD_VAR(v)		XEM_ADD_NVAR(#v,(v))
 #define XEM_ADD_IOEF(n) 	if (IOERROR_FIELDVALID(ioe,n))		    \
 				    XEM_ADD_NVAR("ioe." #n,		    \
 						 IOERROR_GETVALUE(ioe,n))
 
-#ifdef IRIX
+#ifdef LATER
 static void
 xem_add_ioe(ioerror_t *ioe)
 {
@@ -891,7 +847,7 @@
 }
 
 #define XEM_ADD_IOE()	(xem_add_ioe(ioe))
-#endif	/* IRIX */
+#endif	/* LATER */
 
 int                     xbow_xmit_retry_errors = 0;
 
@@ -971,7 +927,6 @@
 static void
 xbow_errintr_handler(intr_arg_t arg)
 {
-#ifdef IRIX
     ioerror_t               ioe[1];
     xbow_soft_t             soft = (xbow_soft_t) arg;
     xbow_t                 *xbow = soft->base;
@@ -1065,9 +1020,8 @@
 		    xwidget_vhdl = xbow_widget_lookup(soft->busv,port);
 		    xwidget_name = xwidget_name_get(xwidget_vhdl);
 
-#ifdef IRIX
-		    cmn_err(CE_CONT,
-			    "%s port %X[%s] XIO Bus Error",
+#ifdef	LATER
+		    printk("%s port %X[%s] XIO Bus Error",
 			    soft->name, port, xwidget_name);
 		    if (link_status & XB_STAT_MULTI_ERR)
 			XEM_ADD_STR("\tMultiple Errors\n");
@@ -1089,8 +1043,7 @@
 			XEM_ADD_STR("\tMaximum Request Timeout\n");
 		    if (link_status & XB_STAT_SRC_TOUT_ERR)
 			XEM_ADD_STR("\tSource Timeout Error\n");
-#endif
-
+#endif	/* LATER */
 		    {
 			int                     other_port;
 
@@ -1130,8 +1083,7 @@
 			| XB_WID_STAT_XTALK_ERR
 			| XB_WID_STAT_REG_ACC_ERR)) {
 
-	    cmn_err(CE_CONT,
-		    "%s Port 0 XIO Bus Error",
+	    printk("%s Port 0 XIO Bus Error",
 		    soft->name);
 	    if (wid_stat & XB_WID_STAT_MULTI_ERR)
 		XEM_ADD_STR("\tMultiple Error\n");
@@ -1150,9 +1102,8 @@
 	XEM_ADD_VAR(wid_err_upper);
 	XEM_ADD_VAR(wid_err_lower);
 	XEM_ADD_VAR(wid_err_addr);
-	cmn_err_tag(8, CE_PANIC, "XIO Bus Error");
+	PRINT_PANIC("XIO Bus Error");
     }
-#endif
 }
 #endif	/* LATER */
 
@@ -1180,7 +1131,6 @@
 		      ioerror_mode_t mode,
 		      ioerror_t *ioerror)
 {
-#ifdef IRIX
     int                     retval = IOERROR_WIDGETLEVEL;
 
     xbow_soft_t             soft = (xbow_soft_t) einfo;
@@ -1204,7 +1154,7 @@
     busv = soft->busv;
 
 #if DEBUG && ERROR_DEBUG
-    cmn_err(CE_CONT, "%s: xbow_error_handler\n", soft->name, busv);
+    printk("%s: xbow_error_handler\n", soft->name, busv);
 #endif
 
     port = IOERROR_GETVALUE(ioerror, widgetnum);
@@ -1217,14 +1167,12 @@
 	    return IOERROR_HANDLED;
 
 	if (error_code & IOECODE_DMA) {
-	    cmn_err(CE_ALERT,
-		    "DMA error blamed on Crossbow at %s\n"
+	    PRINT_ALERT("DMA error blamed on Crossbow at %s\n"
 		    "\tbut Crosbow never initiates DMA!",
 		    soft->name);
 	}
 	if (error_code & IOECODE_PIO) {
-	    cmn_err(CE_ALERT,
-		    "PIO Error on XIO Bus %s\n"
+	    PRINT_ALERt("PIO Error on XIO Bus %s\n"
 		    "\tattempting to access XIO controller\n"
 		    "\twith offset 0x%X",
 		    soft->name,
@@ -1258,14 +1206,12 @@
 	    return IOERROR_HANDLED;
 
 	if (error_code & IOECODE_DMA) {
-	    cmn_err(CE_ALERT,
-		    "DMA error blamed on XIO port at %s/%d\n"
+	    PRINT_ALERT("DMA error blamed on XIO port at %s/%d\n"
 		    "\tbut Crossbow does not support that port",
 		    soft->name, port);
 	}
 	if (error_code & IOECODE_PIO) {
-	    cmn_err(CE_ALERT,
-		    "PIO Error on XIO Bus %s\n"
+	    PRINT_ALERT("PIO Error on XIO Bus %s\n"
 		    "\tattempting to access XIO port %d\n"
 		    "\t(which Crossbow does not support)"
 		    "\twith offset 0x%X",
@@ -1309,14 +1255,12 @@
 	    return IOERROR_HANDLED;
 
 	if (error_code & IOECODE_DMA) {
-	    cmn_err(CE_ALERT,
-		    "DMA error blamed on XIO port at %s/%d\n"
+	    PRINT_ALERT("DMA error blamed on XIO port at %s/%d\n"
 		    "\tbut there is no device connected there.",
 		    soft->name, port);
 	}
 	if (error_code & IOECODE_PIO) {
-	    cmn_err(CE_ALERT,
-		    "PIO Error on XIO Bus %s\n"
+	    PRINT_ALERT("PIO Error on XIO Bus %s\n"
 		    "\tattempting to access XIO port %d\n"
 		    "\t(which has no device connected)"
 		    "\twith offset 0x%X",
@@ -1349,16 +1293,14 @@
 	if (mode == MODE_DEVPROBE)
 	    return IOERROR_HANDLED;
 
-	cmn_err(CE_ALERT,
-		"%s%sError on XIO Bus %s port %d",
+	PRINT_ALERT("%s%sError on XIO Bus %s port %d",
 		(error_code & IOECODE_DMA) ? "DMA " : "",
 		(error_code & IOECODE_PIO) ? "PIO " : "",
 		soft->name, port);
 
 	if ((error_code & IOECODE_PIO) &&
 	    (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
-	    cmn_err(CE_CONT,
-		    "\tAccess attempted to offset 0x%X\n",
+	    printk("\tAccess attempted to offset 0x%X\n",
 		    IOERROR_GETVALUE(ioerror, xtalkaddr));
 	}
 	if (link_aux_status & XB_AUX_LINKFAIL_RST_BAD)
@@ -1393,16 +1335,14 @@
     if (retval == IOERROR_UNHANDLED) {
 	retval = IOERROR_PANIC;
 
-	cmn_err(CE_ALERT,
-		"%s%sError on XIO Bus %s port %d",
+	PRINT_ALERT("%s%sError on XIO Bus %s port %d",
 		(error_code & IOECODE_DMA) ? "DMA " : "",
 		(error_code & IOECODE_PIO) ? "PIO " : "",
 		soft->name, port);
 
 	if ((error_code & IOECODE_PIO) &&
 	    (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
-	    cmn_err(CE_CONT,
-		    "\tAccess attempted to offset 0x%X\n",
+	    printk("\tAccess attempted to offset 0x%X\n",
 		    IOERROR_GETVALUE(ioerror, xtalkaddr));
 	}
     }
@@ -1428,7 +1368,6 @@
      */
 
     return retval;
-#endif /* IRIX */
 }
 
 #endif	/* LATER */
@@ -1440,7 +1379,8 @@
     xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
     xbow_perf_link_t       *xbow_plink = xbow_soft->xbow_perflink;
     xbow_perfcount_t        perf_reg;
-    int                     link, s, i;
+    unsigned long           s;
+    int                     link, i;
 
     for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) {
 	if (xbow_perf->xp_mode == XBOW_MONITOR_NONE)
@@ -1460,7 +1400,7 @@
     }
     /* Do port /mode multiplexing here */
 
-#ifdef IRIX
+#ifdef LATER
     (void) timeout(xbow_update_perf_counters,
 		   (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT);
 #endif
@@ -1484,7 +1424,8 @@
     xbow_linkctrl_t         xbow_link_ctrl;
     xbow_t                 *xbow = xbow_soft->base;
     xbow_perfcount_t        perf_reg;
-    int                     s, i;
+    unsigned long           s;
+    int                     i;
 
     link -= BASE_XBOW_PORT;
     if ((link < 0) || (link >= MAX_XBOW_PORTS))
@@ -1525,7 +1466,7 @@
     *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val;
     xbow_perf->xp_current = perf_reg.xb_perf.count;
 
-#ifdef IRIX
+#ifdef LATER
     (void) timeout(xbow_update_perf_counters,
 		   (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT);
 #endif
@@ -1578,13 +1519,13 @@
 	    aux_sts.xb_aux_linkstatus.tx_retry_cnt;
 
 	if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) {
-#ifdef IRIX
-	    cmn_err(CE_WARN, "link %d[%s]: bad status 0x%x\n",
+#ifdef	LATER
+	    PRINT_WARNING("link %d[%s]: bad status 0x%x\n",
 		    link, xwidget_name, lnk_sts.linkstatus);
 #endif
 	}
     }
-#ifdef IRIX
+#ifdef LATER
     if (xbow_soft->link_monitor)
 	(void) timeout(xbow_update_llp_status,
 		       (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT);
@@ -1611,7 +1552,7 @@
 {
     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
 
-#ifdef IRIX
+#ifdef LATER
     (void) timeout(xbow_update_llp_status,
 		   (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT);
 #endif
@@ -1690,7 +1631,7 @@
     int                     i;
     xb_linkregs_t          *link;
 
-#ifdef IRIX
+#ifdef LATER
     if (dev_is_vertex((devfs_handle_t) regs)) {
 	devfs_handle_t            vhdl = (devfs_handle_t) regs;
 	xbow_soft_t             soft = xbow_soft_get(vhdl);
@@ -1702,7 +1643,7 @@
 	xbow = (xbow_t *) regs;
     }
 
-#ifdef IRIX
+#ifdef LATER
     qprintf("Printing xbow registers starting at 0x%x\n", xbow);
     qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %x\n",
 	    xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper,
@@ -1716,7 +1657,7 @@
 
     for (i = 8; i <= 0xf; i++) {
 	link = &xbow->xb_link(i);
-#ifdef IRIX
+#ifdef LATER
 	qprintf("Link %d registers\n", i);
 	qprintf("\tctrl %x stat %x arbuppr %x arblowr %x auxstat %x\n",
 		link->link_control, link->link_status,
@@ -1795,7 +1736,7 @@
     xbow_soft_t             soft = xbow_soft_get(vhdl);
     volatile xbowreg_t     *xreg;
     xbowreg_t               mask;
-    int                     s;
+    unsigned long           s;
     int                     error = 0;
     bandwidth_t             old_bw_BYTES, req_bw_BYTES;
     xbowreg_t               old_xreg;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/xswitch.c linux/arch/ia64/sn/io/xswitch.c
--- v2.4.3/linux/arch/ia64/sn/io/xswitch.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/xswitch.c	Thu Apr  5 12:51:47 2001
@@ -88,13 +88,15 @@
 
     xswitch_info = (xswitch_info_t)
 	hwgraph_fastinfo_get(xwidget);
-#ifdef IRIX
+#ifdef	LATER
     if ((xswitch_info != NULL) &&
 	(xswitch_info->fingerprint != xswitch_info_fingerprint))
-	cmn_err(CE_PANIC, "%v xswitch_info_get bad fingerprint", xwidget);
+#ifdef SUPPORT_PRINTING_V_FORMAT
+	PRINT_PANIC("%v xswitch_info_get bad fingerprint", xwidget);
+#else
+	PRINT_PANIC("%x xswitch_info_get bad fingerprint", xwidget);
 #endif
-
-    printk("xswitch_info_get: xwidget 0x%p xswitch_info 0x%p\n", xwidget, xswitch_info);
+#endif	/* LATER */
 
     return (xswitch_info);
 }
@@ -118,9 +120,9 @@
 xswitch_info_vhdl_get(xswitch_info_t xswitch_info,
 		      xwidgetnum_t port)
 {
-#ifdef IRIX
+#ifdef	LATER
     if (xswitch_info == NULL)
-	cmn_err(CE_PANIC, "xswitch_info_vhdl_get: null xswitch_info");
+	PRINT_PANIC("xswitch_info_vhdl_get: null xswitch_info");
 #endif
 
 #if XSWITCH_CENSUS_PORT_MIN
@@ -196,8 +198,6 @@
 					       GRAPH_VERTEX_NONE);
 	}
 	xswitch_info_set(xwidget, xswitch_info);
-	printk("xswitch_info_new: xswitch_info_set xwidget 0x%p, xswitch_info 0x%p\n",
-		xwidget, xswitch_info);
     }
     return xswitch_info;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/xtalk.c linux/arch/ia64/sn/io/xtalk.c
--- v2.4.3/linux/arch/ia64/sn/io/xtalk.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/ia64/sn/io/xtalk.c	Thu Apr 12 12:16:35 2001
@@ -9,7 +9,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/iobus.h>
@@ -71,6 +70,7 @@
 void			xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t);
 void			xtalk_dmalist_drain(devfs_handle_t, alenlist_t);
 xtalk_intr_t            xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t);
+xtalk_intr_t            xtalk_intr_alloc_nothd(devfs_handle_t, device_desc_t, devfs_handle_t);
 void                    xtalk_intr_free(xtalk_intr_t);
 int                     xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *, void *);
 void                    xtalk_intr_disconnect(xtalk_intr_t);
@@ -318,7 +318,7 @@
 			       unsigned flags)
 {
 #if DEBUG
-    cmn_err(CE_PANIC, "null_xtalk_early_piotrans_addr");
+    PRINT_PANIC("null_xtalk_early_piotrans_addr");
 #endif
     return NULL;
 }
@@ -439,6 +439,19 @@
 	(dev, dev_desc, owner_dev);
 }
 
+/*
+ * Allocate resources required for an interrupt as specified in dev_desc.
+ * Unconditionally setup resources to be non-threaded.
+ * Return resource handle in intr_hdl.
+ */
+xtalk_intr_t
+xtalk_intr_alloc_nothd(devfs_handle_t dev,	/* which Crosstalk device */
+		 	device_desc_t dev_desc,	/* device descriptor */
+		 	devfs_handle_t owner_dev)	/* owner of this interrupt */
+{
+    return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc_nothd)
+	(dev, dev_desc, owner_dev);
+}
 
 /*
  * Free resources consumed by intr_alloc.
@@ -527,7 +540,11 @@
     xwidget_info_t          xwidget_info;
 
 #if DEBUG && ERROR_DEBUG
-    cmn_err(CE_CONT, "%v: xtalk_error_handler\n", xconn);
+#ifdef SUPPORT_PRINTING_V_FORMAT
+    printk("%v: xtalk_error_handler\n", xconn);
+#else
+    printk("%x: xtalk_error_handler\n", xconn);
+#endif
 #endif
 
     xwidget_info = xwidget_info_get(xconn);
@@ -549,9 +566,13 @@
 	(mode == MODE_DEVREENABLE))
 	return IOERROR_HANDLED;
 
-#ifdef IRIX
-    cmn_err(CE_WARN, "Xbow at %v encountered Fatal error", xconn);
+#ifdef	LATER
+#ifdef SUPPORT_PRINTING_V_FORMAT
+    PRINT_WARNING("Xbow at %v encountered Fatal error", xconn);
+#else
+    PRINT_WARNING("Xbow at %x encountered Fatal error", xconn);
 #endif
+#endif	/* LATER */
     ioerror_dump("xtalk", error_code, mode, ioerror);
 
     return IOERROR_UNHANDLED;
@@ -648,13 +669,6 @@
     return (xtalk_intr->xi_sfarg);
 }
 
-
-int
-xtalk_intr_flags_get(xtalk_intr_t xtalk_intr)
-{
-	return(xtalk_intr->xi_flags);
-}
-
 /****** Generic crosstalk pio interfaces ******/
 devfs_handle_t
 xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap)
@@ -726,11 +740,15 @@
     widget_info = (xwidget_info_t)
 	hwgraph_fastinfo_get(xwidget);
 
-#ifdef IRIX
+#ifdef	LATER
     if ((widget_info != NULL) &&
 	(widget_info->w_fingerprint != widget_info_fingerprint))
-	cmn_err(CE_PANIC, "%v bad xwidget_info", xwidget);
+#ifdef SUPPORT_PRINTING_V_FORMAT
+	PRINT_PANIC("%v bad xwidget_info", xwidget);
+#else
+	PRINT_PANIC("%x bad xwidget_info", xwidget);
 #endif
+#endif	/* LATER */
 
     return (widget_info);
 }
@@ -894,7 +912,7 @@
 
     return cdl_add_driver(xtalk_registry,
 			  part_num, mfg_num,
-			  driver_prefix, flags);
+			  driver_prefix, flags, NULL);
 }
 
 /*
@@ -910,7 +928,7 @@
      */
     ASSERT(xtalk_registry != NULL);
 
-    cdl_del_driver(xtalk_registry, driver_prefix);
+    cdl_del_driver(xtalk_registry, driver_prefix, NULL);
 }
 
 /*
@@ -963,7 +981,6 @@
      * long as we have it, we can use it elsewhere.
      */
     s = dev_to_name(widget,devnm,MAXDEVNAME);
-    printk("xwidget_register: dev_to_name widget id 0x%p, s = %s\n", widget, s);
     widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
     strcpy(widget_info->w_name,s);
     
@@ -985,7 +1002,8 @@
     if (aa)
 	    async_attach_add_info(widget, aa);
 
-    return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num, widget);
+    return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
+                          widget, 0);
 }
 
 /*
@@ -1009,8 +1027,8 @@
     
     hwid = &(widget_info->w_hwid);
 
-    cdl_del_connpt(xtalk_registry, hwid->part_num, 
-		   hwid->mfg_num, widget);
+    cdl_del_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
+                   widget, 0);
 
     /* Clean out the xwidget information */
     (void)kfree(widget_info->w_name);
@@ -1051,7 +1069,7 @@
 
     xswitch_reset_link(xwidget);
     info = xwidget_info_get(xwidget);
-#ifdef IRIX
+#ifdef LATER
     ASSERT_ALWAYS(info != NULL);
 #endif
 
@@ -1083,26 +1101,7 @@
 	ASSERT(info != NULL);
 	return(xwidget_info_name_get(info));
 }
-/*
- * xtalk_device_powerup
- *	Reset and initialize the specified xtalk widget
- */
-int 
-xtalk_device_powerup(devfs_handle_t xbus_vhdl, xwidgetnum_t widget)
-{
-#ifndef CONFIG_IA64_SGI_IO
-	extern void	io_xswitch_widget_init(devfs_handle_t,
-					       devfs_handle_t,
-					       xwidgetnum_t,
-					       async_attach_t);
-	io_xswitch_widget_init(xbus_vhdl, 
-			       hwgraph_connectpt_get(xbus_vhdl),
-			       widget,
-			       NULL);
-#endif	/* CONFIG_IA64_SGI_IO */
-	
-	return(0);
-}
+
 /*
  * xtalk_device_shutdown
  *	Disable  the specified xtalk widget and clean out all the software
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/Makefile linux/arch/ia64/sn/sn1/Makefile
--- v2.4.3/linux/arch/ia64/sn/sn1/Makefile	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/sn1/Makefile	Thu Apr  5 12:51:47 2001
@@ -8,7 +8,7 @@
 EXTRA_CFLAGS	:= -DSN -DLANGUAGE_C=1 -D_LANGUAGE_C=1 -I. -DBRINGUP \
 		   -DDIRECT_L1_CONSOLE -DNUMA_BASE -DSIMULATED_KLGRAPH \
 		   -DNUMA_MIGR_CONTROL -DLITTLE_ENDIAN -DREAL_HARDWARE \
-		   -DNEW_INTERRUPTS -DCONFIG_IA64_SGI_IO
+		   -DNEW_INTERRUPTS
 
 .S.s:
 	$(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -o $*.s $<
@@ -18,18 +18,13 @@
 all: sn1.a
 
 O_TARGET        = sn1.a
-O_HEADERS       =
-O_OBJS          = irq.o setup.o iomv.o mm.o smp.o synergy.o sn1_asm.o \
-		discontig.o
 
-ifeq ($(CONFIG_IA64_SGI_AUTOTEST),y)
-O_OBJS          += llsc4.o
-endif
+obj-y          = irq.o setup.o iomv.o mm.o smp.o synergy.o sn1_asm.o \
+		discontig.o probe.o error.o sv.o
 
-
-ifeq ($(CONFIG_IA64_GENERIC),y)
-O_OBJS		+= machvec.o
-endif
+obj-$(CONFIG_IA64_SGI_AUTOTEST)	+= llsc4.o
+obj-$(CONFIG_IA64_GENERIC)	+= machvec.o
+obj-$(CONFIG_MODULES)		+= sn1_ksyms.o
 
 clean::
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/discontig.c linux/arch/ia64/sn/sn1/discontig.c
--- v2.4.3/linux/arch/ia64/sn/sn1/discontig.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/sn1/discontig.c	Thu Apr  5 12:51:47 2001
@@ -139,35 +139,6 @@
 	dump_bootmem_info() ;
 }
 
-void __init
-discontig_paging_init(void)
-{
-	int i;
-	unsigned long max_dma, zones_size[MAX_NR_ZONES];
-	void dump_node_data(void);
-
-        max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-	for (i = 0; i < numnodes; i++) {
-	       extern void free_unused_memmap_node(int);
-               unsigned long startpfn = __pa((void *)NODE_START(i)) >> PAGE_SHIFT;
-               unsigned long numpfn = NODE_SIZE(i) >> PAGE_SHIFT;
-               memset(zones_size, 0, sizeof(zones_size));
-
-               if ((startpfn + numpfn) < max_dma) {
-                       zones_size[ZONE_DMA] = numpfn;
-               } else if (startpfn > max_dma) {
-                       zones_size[ZONE_NORMAL] = numpfn;
-               } else {
-                       zones_size[ZONE_DMA] = (max_dma - startpfn);
-                       zones_size[ZONE_NORMAL] = numpfn - zones_size[ZONE_DMA];
-               }
-               free_area_init_node(i, NODE_DATA(i), NULL, zones_size, startpfn<<PAGE_SHIFT, 0);
-	       free_unused_memmap_node(i);
-	}
-	dump_node_data();
-}
-
-
 void
 dump_node_data(void)
 {
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/error.c linux/arch/ia64/sn/sn1/error.c
--- v2.4.3/linux/arch/ia64/sn/sn1/error.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/sn1/error.c	Thu Apr  5 12:51:47 2001
@@ -0,0 +1,149 @@
+
+
+/*
+ * SN1 Platform specific error Support
+ *
+ * Copyright (C) 2001 Silicon Graphics, Inc.
+ * Copyright (C) 2001 Alan Mayer (ajm@sgi.com)
+ */
+
+
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/ptrace.h>
+#include <linux/devfs_fs_kernel.h>
+#include <asm/smp.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/sn1/bedrock.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/addrs.h>
+
+void
+snia_error_intr_handler(int irq, void *devid, struct pt_regs *pt_regs) {
+	unsigned long long intpend_val;
+	unsigned long long bit;
+
+	switch (irq) {
+	case SGI_UART_IRQ:
+		// This isn't really an error interrupt.  We're just
+		// here because we have to do something with them.
+		// This is probably wrong, and this code will be
+		// removed.
+		intpend_val = LOCAL_HUB_L(PI_INT_PEND0);
+		if ( (bit = ~(1L<<GFX_INTR_A)) ==
+			(intpend_val & ~(1L<<GFX_INTR_A)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			return;
+		}
+		if ( (bit = ~(1L<<GFX_INTR_B)) ==
+			(intpend_val & ~(1L<<GFX_INTR_B)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			return;
+		}
+		if ( (bit = ~(1L<<PG_MIG_INTR)) ==
+			(intpend_val & ~(1L<<PG_MIG_INTR)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			return;
+		}
+		if ( (bit = ~(1L<<UART_INTR)) ==
+			(intpend_val & ~(1L<<UART_INTR)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			return;
+		}
+		if ( (bit = ~(1L<<CC_PEND_A)) ==
+			(intpend_val & ~(1L<<CC_PEND_A)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			return;
+		}
+		if ( (bit = ~(1L<<CC_PEND_B)) ==
+			(intpend_val & ~(1L<<CC_PEND_B)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			return;
+		}
+		printk("Received SGI_UART_IRQ (65), but no intpend0 bits were set???\n");
+		return;
+	case SGI_HUB_ERROR_IRQ:
+		// These are mostly error interrupts of various
+		// sorts.  We need to do more than panic here, but
+		// what the heck, this is bring up.
+		intpend_val = LOCAL_HUB_L(PI_INT_PEND1);
+		
+		if ( (bit = ~(1L<<XB_ERROR)) ==
+			(intpend_val & ~(1L<<XB_ERROR)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED XB_ERROR on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		if ( (bit = ~(1L<<LB_ERROR)) ==
+			(intpend_val & ~(1L<<LB_ERROR)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED LB_ERROR on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		if ( (bit = ~(1L<<NACK_INT_A)) ==
+			(intpend_val & ~(1L<<NACK_INT_A)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED NACK_INT_A on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		if ( (bit = ~(1L<<NACK_INT_B)) ==
+			(intpend_val & ~(1L<<NACK_INT_B)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED NACK_INT_B on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		if ( (bit = ~(1L<<CLK_ERR_INTR)) ==
+			(intpend_val & ~(1L<<CLK_ERR_INTR)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED CLK_ERR_INTR on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		if ( (bit = ~(1L<<COR_ERR_INTR_A)) ==
+			(intpend_val & ~(1L<<COR_ERR_INTR_A)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED COR_ERR_INTR_A on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		if ( (bit = ~(1L<<COR_ERR_INTR_B)) ==
+			(intpend_val & ~(1L<<COR_ERR_INTR_B)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED COR_ERR_INTR_B on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		if ( (bit = ~(1L<<MD_COR_ERR_INTR)) ==
+			(intpend_val & ~(1L<<MD_COR_ERR_INTR)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED MD_COR_ERR_INTR on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		if ( (bit = ~(1L<<NI_ERROR_INTR)) ==
+			(intpend_val & ~(1L<<NI_ERROR_INTR)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED NI_ERROR_INTR on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		if ( (bit = ~(1L<<MSC_PANIC_INTR)) ==
+			(intpend_val & ~(1L<<MSC_PANIC_INTR)) ) {
+			LOCAL_HUB_CLR_INTR(bit);
+			panic("RECEIVED MSC_PANIC_INTR on cpu %d, cnode %d\n",
+				smp_processor_id(), 
+				cpuid_to_cnodeid(smp_processor_id()));
+		}
+		printk("Received SGI_XB_ERROR_IRQ (182) but no intpend1 bits are set???\n");
+		return;
+	default:
+		printk("Received invalid irq in snia_error_intr_handler()/n");
+	}
+}
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/iomv.c linux/arch/ia64/sn/sn1/iomv.c
--- v2.4.3/linux/arch/ia64/sn/sn1/iomv.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/sn1/iomv.c	Thu Apr  5 12:51:47 2001
@@ -25,11 +25,8 @@
  		 * for accessing registers in bedrock local block
  		 * (so we don't do port&0xfff)
  		 */
-		if (port == 0x1f6 || port == 0x1f7
-			|| port == 0x3f6 || port == 0x3f7
-			|| port == 0x1f0 || port == 0x1f1
-			|| port == 0x1f3 || port == 0x1f4
-			|| port == 0x1f2 || port == 0x1f5)  {
+		if (port >= 0x1f0 && port <= 0x1f7 ||
+			port == 0x3f6 || port == 0x3f7) {
 			io_base = __IA64_UNCACHED_OFFSET | 0x00000FFFFC000000;
 			addr = io_base | ((port >> 2) << 12) | (port & 0xfff);
 		} else {
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/irq.c linux/arch/ia64/sn/sn1/irq.c
--- v2.4.3/linux/arch/ia64/sn/sn1/irq.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/sn1/irq.c	Thu Apr  5 12:51:47 2001
@@ -4,11 +4,13 @@
  * Copyright (C) 2000   Silicon Graphics
  * Copyright (C) 2000   Jack Steiner (steiner@sgi.com)
  * Copyright (C) 2000   Alan Mayer (ajm@sgi.com)
+ * Copyright (C) 2000   Kanoj Sarcar (kanoj@sgi.com)
  */
 
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 #include <asm/current.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
@@ -30,28 +32,23 @@
 #include <asm/sn/sn1/arch.h>
 #include <asm/sn/synergy.h>
 
+#define IRQ_BIT_OFFSET 64
 
-int bit_pos_to_irq(int bit);
-int irq_to_bit_pos(int irq);
-void add_interrupt_randomness(int irq);
-void * kmalloc(size_t size, int flags);
-void kfree(const void *);
-int sgi_pci_intr_support (unsigned int, device_desc_t *, devfs_handle_t *, pciio_intr_line_t *, devfs_handle_t *);
-pciio_intr_t pciio_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t);
-int request_irq(unsigned int, void (*)(int, void *, struct pt_regs *), unsigned long, const char *, void *);
-
-/* This should be dynamically allocated, at least part of it. */
-/* For the time being, though, we'll statically allocate it */
-/* because kmalloc hasn't been initiallized at the time this */
-/* array is initiallized.  One way to do it would be to statically */
-/* allocate the data for node 0, then let other nodes, as they */
-/* need it, dynamically allocate their own data space. */
-
-struct sn1_cnode_action_list *sn1_node_actions[MAX_COMPACT_NODES];
-struct sn1_cnode_action_list sn1_actions[MAX_COMPACT_NODES][256];
+int bit_pos_to_irq(int bit)
+{
+	if (bit > 118)
+		bit = 118;
+	return (bit + IRQ_BIT_OFFSET);
+}
 
+static inline int irq_to_bit_pos(int irq)
+{
+	int bit = irq - IRQ_BIT_OFFSET;
 
-extern int numnodes;
+	if (bit > 63)
+		bit -= 64;
+	return bit;
+}
 
 static unsigned int
 sn1_startup_irq(unsigned int irq)
@@ -82,6 +79,10 @@
 static void
 sn1_end_irq(unsigned int irq)
 {
+	int bit;
+
+	bit = irq_to_bit_pos(irq);
+	LOCAL_HUB_CLR_INTR(bit);
 }
 
 static void
@@ -89,38 +90,6 @@
 {
 }
 
-
-static void
-sn1_handle_irq(int irq, void *dummy, struct pt_regs *regs)
-{
-	int bit, cnode;
-	struct sn1_cnode_action_list *alp;
-	struct sn1_intr_action *ap;
-	void (*handler)(int, void *, struct pt_regs *);
-	unsigned long flags = 0;
-	int cpuid = smp_processor_id();
-
-
-	bit = irq_to_bit_pos(irq);
-	LOCAL_HUB_CLR_INTR(bit);
-	cnode = cpuid_to_cnodeid(cpuid);
-	alp = sn1_node_actions[cnode];
-	ap = alp[irq].action_list;
-	if (ap == NULL) {
-		return;
-	}
-	while (ap) {
-		flags |= ap->flags;
-		handler = ap->handler;
-		(*handler)(irq,ap->intr_arg,regs);
-		ap = ap->next;
-	}
-	if ((flags & SA_SAMPLE_RANDOM) != 0)
-                add_interrupt_randomness(irq);
-
-        return;
-}
-
 struct hw_interrupt_type irq_type_sn1 = {
         "sn1_irq",
         sn1_startup_irq,
@@ -132,134 +101,83 @@
         sn1_set_affinity_irq
 };
 
-struct irqaction sn1_irqaction = {
-	sn1_handle_irq,
-	0,
-	0,
-	NULL,
-	NULL,
-	NULL,
-};
 
 void
 sn1_irq_init (void)
 {
-	int i,j;
+	int i;
 
 	for (i = 0; i <= NR_IRQS; ++i) {
-		if (irq_desc[i].handler == &no_irq_type) {
-			irq_desc[i].handler = &irq_type_sn1;
-			if (i >=71 && i <= 181) {
-				irq_desc[i].action = &sn1_irqaction;
-			}
-		}
-	}
-
-	for (i = 0; i < numnodes; i++) {
-		sn1_node_actions[i] = sn1_actions[i];
-		memset(sn1_node_actions[i], 0,
-			sizeof(struct sn1_cnode_action_list) *
-			(IA64_MAX_VECTORED_IRQ + 1));
-		for (j=0; j<IA64_MAX_VECTORED_IRQ+1; j++) {
-			spin_lock_init(&sn1_node_actions[i][j].action_list_lock);
+		if (idesc_from_vector(i)->handler == &no_irq_type) {
+			idesc_from_vector(i)->handler = &irq_type_sn1;
 		}
 	}
 }
 
 
-int          
-sn1_request_irq (unsigned int requested_irq, void (*handler)(int, void *, struct pt_regs *),
-             unsigned long irqflags, const char * devname, void *dev_id)
-{ 
-	devfs_handle_t curr_dev;
-	devfs_handle_t dev;
-	pciio_intr_t intr_handle;
-	pciio_intr_line_t line;
-	device_desc_t dev_desc;
-        int cpuid, bit, cnode;
-	struct sn1_intr_action *ap, *new_ap;
-	struct sn1_cnode_action_list *alp;
-	int irq;
-
-	if ( (requested_irq & 0xff) == 0 ) {
-		int ret;
-
-		sgi_pci_intr_support(requested_irq,
-			&dev_desc, &dev, &line, &curr_dev);
-		intr_handle = pciio_intr_alloc(curr_dev, NULL, line, curr_dev);
-		bit = intr_handle->pi_irq;
-		cpuid = intr_handle->pi_cpu;
-		irq = bit_pos_to_irq(bit);
-		cnode = cpuid_to_cnodeid(cpuid);
-		new_ap = (struct sn1_intr_action *)kmalloc(
-			sizeof(struct sn1_intr_action), GFP_KERNEL);
-		irq_desc[irq].status = 0;
-		new_ap->handler = handler;
-		new_ap->intr_arg = dev_id;
-		new_ap->flags = irqflags;
-		new_ap->next = NULL;
-		alp = sn1_node_actions[cnode];
-
-		spin_lock(&alp[irq].action_list_lock);
-		ap = alp[irq].action_list;
-		/* check action list for "share" consistency */
-		while (ap){
-			if (!(ap->flags & irqflags & SA_SHIRQ) ) {
-				return(-EBUSY);
-				spin_unlock(&alp[irq].action_list_lock);
-			}
-			ap = ap->next;
-		}
-		ap = alp[irq].action_list;
-		if (ap) {
-			while (ap->next) {
-				ap = ap->next;
-			}
-			ap->next = new_ap;
-		} else {
-			alp[irq].action_list = new_ap;
-		}
-		ret = pciio_intr_connect(intr_handle, (intr_func_t)handler, dev_id, NULL);
-		if (ret) { /* connect failed, undo what we did. */
-			new_ap = alp[irq].action_list;
-			if (new_ap == ap) {
-				alp[irq].action_list = NULL;
-				kfree(ap);
-			} else {
-				while (new_ap->next && new_ap->next != ap) {
-					new_ap = new_ap->next;
-				}
-				if (new_ap->next == ap) {
-					new_ap->next = ap->next;
-					kfree(ap);
-				}
-			}
-		}
-			
-		spin_unlock(&alp[irq].action_list_lock);
-		return(ret);
-	} else {
-		return(request_irq(requested_irq, handler, irqflags, devname, dev_id));
-	}
-}
 
-#if !defined(CONFIG_IA64_SGI_IO)
+#if !defined(CONFIG_IA64_SGI_SN1)
 void
 sn1_pci_fixup(int arg)
 {
 }
 #endif
 
-int
-bit_pos_to_irq(int bit) {
-#define BIT_TO_IRQ 64
+#ifdef CONFIG_PERCPU_IRQ
+
+extern irq_desc_t irq_descX[NR_IRQS];
+irq_desc_t *irq_desc_ptr[NR_CPUS] = { irq_descX };
+
+/*
+ * Each slave AP allocates its own irq table.
+ */
+int __init cpu_irq_init(void)
+{
+	irq_desc_ptr[smp_processor_id()] = (irq_desc_t *)kmalloc(sizeof(irq_descX), GFP_KERNEL);
+	if (irq_desc_ptr[smp_processor_id()] == 0)
+		return(-1);
+	memcpy(irq_desc_ptr[smp_processor_id()], irq_desc_ptr[0], 
+							sizeof(irq_descX));
+	return(0);
+}
+
+/*
+ * This can also allocate the irq tables for the other cpus, specifically
+ * on their nodes.
+ */
+int __init master_irq_init(void)
+{
+	return(0);
+}
+
+/*
+ * The input is an ivt level.
+ */
+irq_desc_t *idesc_from_vector(unsigned int ivnum)
+{
+	return(irq_desc_ptr[smp_processor_id()] + ivnum);
+}
 
-        return bit + BIT_TO_IRQ;
+/*
+ * The input is a "soft" level, that we encoded in.
+ */
+irq_desc_t *idesc_from_irq(unsigned int irq)
+{
+	return(irq_desc_ptr[irq >> 8] + (irq & 0xff));
 }
 
-int
-irq_to_bit_pos(int irq) {
-#define IRQ_TO_BIT 64
+unsigned int ivector_from_irq(unsigned int irq)
+{
+	return(irq & 0xff);
+}
 
-        return irq - IRQ_TO_BIT;
+/*
+ * This should return the Linux irq # for the i/p vector on the
+ * i/p cpu. We currently do not track this.
+ */
+unsigned int irq_from_cpuvector(int cpunum, unsigned int vector)
+{
+	return (vector);
 }
+
+#endif /* CONFIG_PERCPU_IRQ */
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/llsc4.c linux/arch/ia64/sn/sn1/llsc4.c
--- v2.4.3/linux/arch/ia64/sn/sn1/llsc4.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/sn1/llsc4.c	Thu Apr  5 12:51:47 2001
@@ -35,6 +35,15 @@
 static int	inttest=0;
 #endif
 
+#ifdef IA64_SEMFIX_INSN
+#undef IA64_SEMFIX_INSN
+#endif
+#ifdef IA64_SEMFIX
+#undef IA64_SEMFIX
+#endif
+# define IA64_SEMFIX_INSN
+# define IA64_SEMFIX    ""
+
 
 /*
  * Test parameter table for AUTOTEST
@@ -46,22 +55,22 @@
 } autotest_table_t;
 
 autotest_table_t autotest_table[] = {
-	{1000000,	2,	0x2b4		},
-	{1000000,	16,	0,		},
-	{1000000,	16,	4,		},
-	{1000000,	128,	0x44		},
-	{1000000,	128,	0x84		},
-	{1000000,	128,	0x200		},
-	{1000000,	128,	0x204		},
-	{1000000,	128,	0x2b4		},
-	{1000000,	2,	8*MB+0x2b4	},
-	{1000000,	16,	8*MB+0		},
-	{1000000,	16,	8*MB+4		},
-	{1000000,	128,	8*MB+0x44	},
-	{1000000,	128,	8*MB+0x84	},
-	{1000000,	128,	8*MB+0x200	},
-	{1000000,	128,	8*MB+0x204	},
-	{1000000,	128,	8*MB+0x2b4	},
+	{5000000,	2,	0x2b4		},
+	{5000000,	16,	0,		},
+	{5000000,	16,	4,		},
+	{5000000,	128,	0x44		},
+	{5000000,	128,	0x84		},
+	{5000000,	128,	0x200		},
+	{5000000,	128,	0x204		},
+	{5000000,	128,	0x2b4		},
+	{5000000,	2,	8*MB+0x2b4	},
+	{5000000,	16,	8*MB+0		},
+	{5000000,	16,	8*MB+4		},
+	{5000000,	128,	8*MB+0x44	},
+	{5000000,	128,	8*MB+0x84	},
+	{5000000,	128,	8*MB+0x200	},
+	{5000000,	128,	8*MB+0x204	},
+	{5000000,	128,	8*MB+0x2b4	},
 	{0}};
 
 /*
@@ -134,20 +143,21 @@
 static void Speedo(void);
 
 int autotest_enabled=0;
-static int autotest_explicit_flush=0;
 static int llsctest_number=-1;
 static int errstop_enabled=0;
 static int fail_enabled=0;
 static int selective_trigger=0;
+static int dump_block_addrs_opt=0;
+static uint errlock=0;
 
 static int __init autotest_enable(char *str)
 {
         autotest_enabled = 1;
 	return 1;
 }
-static int __init set_llscxflush(char *str)
+static int __init set_llscblkadr(char *str)
 {
-	autotest_explicit_flush = 1;
+	dump_block_addrs_opt = 1;
 	return 1;
 }
 static int __init set_llscselt(char *str)
@@ -179,55 +189,39 @@
 	printk ("  Test options:\n");
 	printk ("     llsctest=<n>\t%d\tTest number to run (all = -1)\n", llsctest_number);
 	printk ("     llscerrstop \t%s\tStop on error\n", errstop_enabled ? "on" : "off");
-	printk ("     llscxflush  \t%s\tEnable explicit FC in test\n", autotest_explicit_flush ? "on" : "off");
 	printk ("     llscfail    \t%s\tForce a failure to test the trigger & error messages\n", fail_enabled ? "on" : "off");
 	printk ("     llscselt    \t%s\tSelective triger on failures\n", selective_trigger ? "on" : "off");
+	printk ("     llscblkadr  \t%s\tDump data block addresses\n", dump_block_addrs_opt ? "on" : "off");
+	printk ("  SEMFIX: %s\n", IA64_SEMFIX);
 	printk ("\n");
 }
 __setup("autotest", autotest_enable);
 __setup("llsctest=", set_llsctest);
 __setup("llscerrstop", set_llscerrstop);
-__setup("llscxflush", set_llscxflush);
 __setup("llscfail", set_llscfail);
 __setup("llscselt", set_llscselt);
+__setup("llscblkadr", set_llscblkadr);
 
 
-extern inline void
-flush_buddy(void *p)
-{
-	long	lp;
-
-	if (autotest_explicit_flush)  {
-		lp = (long)p;
-		lp ^= 0x40;
-		asm volatile ("fc %0" :: "r"(lp) : "memory");
-		ia64_sync_i();
-		ia64_srlz_d();
-	}
-}
-
-static int
+extern inline int
 set_lock(uint *lock, uint id)
 {
 	uint	old;
-	flush_buddy(lock);
 	old = cmpxchg_acq(lock, 0, id);
 	return (old == 0);
 }
 
-static int
+extern inline int
 clr_lock(uint *lock, uint id)
 {
 	uint	old;
-	flush_buddy(lock);
 	old = cmpxchg_rel(lock, id, 0);
 	return (old == id);
 }
 
-static void
+extern inline void
 zero_lock(uint *lock)
 {
-	flush_buddy(lock);
 	*lock = 0;
 }
 
@@ -322,7 +316,6 @@
 					return 1;
 				}
 				if (correct_errors) {
-					flush_buddy(privp);
 					tp->private[linei] = *privp;
 				}
 				errs++;
@@ -343,7 +336,6 @@
 				errs++;
 			}
 			pval++;
-			flush_buddy(privp);
 			*privp = pval;
 			tp->private[linei] = pval;
 			break;
@@ -425,9 +417,7 @@
 				errs++;
 			}
 
-			flush_buddy(sharep);
 			*sharep = lockpat;
-			flush_buddy(sharecopy);
 			*sharecopy = lockpat;
 
 
@@ -471,7 +461,7 @@
 static int
 rerr(capture_t *cap, char *msg, void *lp, void *slp, int thread, int pass, int linei, int exp, int found, int stillbad)
 {
-	int		cpu;
+	int		cpu, i;
 	long 		synerr;
 	int		selt;
 
@@ -487,6 +477,11 @@
 	}
 
 	spin(1);
+	i = 100;
+	while (i && set_lock(&errlock, 1) != 1) {
+		spin(1);
+		i--;
+	}
 	printk ("\nDataError!: %-20s, test %ld, thread %d, line:%d, pass %d (0x%x), time %ld expected:%x, found:%x\n",
 	    msg, k_testnumber, thread, linei, pass, pass, jiffies, exp, found);
 
@@ -512,6 +507,7 @@
 		printk("SYNERR: Thread %d, Synerr: 0x%lx\n", thread, synerr);
 	spin(2);
 	printk("\n\n");
+	clr_lock(&errlock, 1);
 
 	if (errstop_enabled) {
 		local_irq_disable();
@@ -639,8 +635,10 @@
 		testnumber = llsctest_number;
 	} else {
 		testnumber++;
-		if (autotest_table[testnumber].passes == 0)
+		if (autotest_table[testnumber].passes == 0) {
 			testnumber = 0;
+			dump_block_addrs_opt = 0;
+		}
 	}
 	k_passes = autotest_table[testnumber].passes;
 	k_linepad = autotest_table[testnumber].linepad;
@@ -704,6 +702,22 @@
 }
 
 static void
+dump_block_addrs(void)
+{
+	int	i;
+
+	printk("LLSC TestNumber %ld\n", k_testnumber);
+
+	for (i=0; i<k_linecount; i++) {
+		printk("  %lx", blocks[i]);
+		if (i%4 == 3)
+			printk("\n");
+	}
+	printk("\n");
+}
+
+
+static void
 set_thread_state(int cpuid, int state)
 {
 	if (k_threadprivate[cpuid]->threadstate == TS_KILLED) {
@@ -717,6 +731,7 @@
 build_mem_map(unsigned long start, unsigned long end, void *arg)
 {
 	long	lstart;
+	long	align = 8*MB;
 	/*
 	 * HACK - skip the kernel on the first node 
 	 */
@@ -731,9 +746,11 @@
 	while (lstart > start && (!PageReserved(virt_to_page(lstart-PAGE_SIZE)) && virt_to_page(lstart-PAGE_SIZE)->count.counter == 0))
 		lstart -= PAGE_SIZE;
 
-	printk ("     memmap: start 0x%lx, end 0x%lx\n", lstart, end);
+	lstart = (lstart + align -1) /align * align;
+	end = end / align * align;
 	if (lstart >= end)
 		return 0;
+	printk ("     memmap: start 0x%lx, end 0x%lx\n", lstart, end);
 
 	memmap[memmapx].vstart = lstart;
 	memmap[memmapx].vend = end;
@@ -812,6 +829,8 @@
 		if (k_linecount > MAX_LINECOUNT) k_linecount = MAX_LINECOUNT;
 		k_linecount = k_linecount & ~1;
 		setup_block_addresses();
+		if (dump_block_addrs_opt)
+			dump_block_addrs();
 
 		k_currentpass = pass++;
 		k_go = ST_RUN;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/machvec.c linux/arch/ia64/sn/sn1/machvec.c
--- v2.4.3/linux/arch/ia64/sn/sn1/machvec.c	Fri Aug 11 19:09:06 2000
+++ linux/arch/ia64/sn/sn1/machvec.c	Thu Apr  5 12:51:47 2001
@@ -1,2 +1,18 @@
 #define MACHVEC_PLATFORM_NAME	sn1
 #include <asm/machvec_init.h>
+#include <asm/io.h>
+#include <linux/pci.h>
+void*
+sn1_mk_io_addr_MACRO
+
+dma_addr_t
+sn1_pci_map_single_MACRO
+
+int
+sn1_pci_map_sg_MACRO
+
+unsigned long
+sn1_virt_to_phys_MACRO
+
+void *
+sn1_phys_to_virt_MACRO
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/mm.c linux/arch/ia64/sn/sn1/mm.c
--- v2.4.3/linux/arch/ia64/sn/sn1/mm.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/sn1/mm.c	Thu Apr  5 12:51:47 2001
@@ -1,7 +1,7 @@
 /*
- * Copyright, 2000, Silicon Graphics.
+ * Copyright, 2000-2001, Silicon Graphics.
  * Copyright Srinivasa Thirumalachar (sprasad@engr.sgi.com)
- * Copyright 2000 Kanoj Sarcar (kanoj@sgi.com)
+ * Copyright 2000-2001 Kanoj Sarcar (kanoj@sgi.com)
  */
 
 #include <linux/config.h>
@@ -11,32 +11,23 @@
 #include <asm/efi.h>
 #include <asm/sn/mmzone_sn1.h>
 
-#       define MIN(a,b)         ((a) < (b) ? (a) : (b))
-#       define MAX(a,b)         ((a) > (b) ? (a) : (b))
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#define MAX(a,b)	((a) > (b) ? (a) : (b))
+
+#define DONE_NOTHING	0
+#define DONE_FINDING	1
+#define DONE_BUILDING	2
 
-/*
- * Note that the nodemem[] data structure does not support arbitrary
- * memory types and memory descriptors inside the node. For example, 
- * you can not have multiple efi-mem-type segments in the node and
- * expect the OS not to use specific mem-types. Currently, the 
- * assumption is that "start" is the start of virtual/physical memory 
- * on the node. PROM can reserve some memory _only_ at the beginning. 
- * This is tracked via the "usable" field, that maintains where the 
- * os can start using memory from on a node (ie end of PROM memory).
- * setup_node_bootmem() is passed the above "usable" value, and is
- * expected to make bootmem calls that ensure lower memory is not used.
- * Note that the bootmem for a node is initialized on the entire node, 
- * without regards to any holes - then we reserve the holes in 
- * setup_sn1_bootmem(), to make sure the holes are not handed out by
- * alloc_bootmem, as well as the corresponding mem_map entries are not
- * considered allocatable by the page_alloc routines.
- */
 struct nodemem_s {
-        u64     start ;
-        u64     end   ;
-        u64 	hole[SN1_MAX_BANK_PER_NODE] ;
-	u64	usable;
-} nodemem[MAXNODES] ;
+        u64     start;	/* start of kernel usable memory */
+        u64     end;	/* end of kernel usable memory */
+	u64	mtot;	/* total kernel usable memory */
+	u64	done;	/* state of bootmem initialization */
+	u64	bstart;	/* where should the bootmem area be */
+	u64	bsize;	/* bootmap size */
+        u64 	hole[SN1_MAX_BANK_PER_NODE];
+} nodemem[MAXNODES];
+
 static int nodemem_valid = 0;
 
 static int __init
@@ -46,7 +37,7 @@
         unsigned long count = 0;
 
 	if (start >= end)
-		return 0 ;
+		return 0;
 
 	/*
 	 * Get the memmap ptrs to the start and end of the holes.
@@ -54,31 +45,33 @@
 	 * Can we do virt_to_page(end), if end is on the next node?
 	 */
 
-	page = virt_to_page(start-1);
-	page++ ;
-	pageend = virt_to_page(end) ;
+	page = virt_to_page(start - 1);
+	page++;
+	pageend = virt_to_page(end);
 
 	printk("hpage=0x%lx, hpageend=0x%lx\n", (u64)page, (u64)pageend) ;
 	free_bootmem_node(NODE_DATA(nid), __pa(page), (u64)pageend - (u64)page);
 
-	return count ;
+	return count;
 }
 
-void
+static void __init
 free_unused_memmap_node(int nid)
 {
-	u64	i = 0 ;
-	u64	holestart = -1 ;
+	u64	i = 0;
+	u64	holestart = -1;
+	u64	start = nodemem[nid].start;
 
+	start = ((start >> SN1_NODE_ADDR_SHIFT) << SN1_NODE_ADDR_SHIFT);
 	do {
-		holestart = nodemem[nid].hole[i] ;
-		i++ ;
+		holestart = nodemem[nid].hole[i];
+		i++;
 		while ((i < SN1_MAX_BANK_PER_NODE) && 
-			(nodemem[nid].hole[i] == (u64)-1))
-			i++ ;
+					(nodemem[nid].hole[i] == (u64)-1))
+			i++;
 		if (i < SN1_MAX_BANK_PER_NODE)
 			free_unused_memmap_hole(nid, holestart, 
-				nodemem[nid].start + (i<<SN1_BANK_ADDR_SHIFT));
+				start + (i<<SN1_BANK_ADDR_SHIFT));
 	} while (i<SN1_MAX_BANK_PER_NODE);
 }
 
@@ -98,7 +91,6 @@
 		cnodeid = NASID_TO_CNODEID(nasid);
 		bankid = GetBankId(__pa(vaddr));
 		nodemem[cnodeid].start = MIN(nodemem[cnodeid].start, vaddr);
-		nodemem[cnodeid].usable = MIN(nodemem[cnodeid].usable, vaddr);
 		nvaddr = (unsigned long)__va((unsigned long)(++nasid) << 
 							SN1_NODE_ADDR_SHIFT);
 		nodemem[cnodeid].end = MAX(nodemem[cnodeid].end, MIN(end, nvaddr));
@@ -118,11 +110,14 @@
 pgtbl_size_ok(int nid)
 {
 	unsigned long numpfn, bank0size, nodesize ;
+	unsigned long start = nodemem[nid].start;
+
+	start = ((start >> SN1_NODE_ADDR_SHIFT) << SN1_NODE_ADDR_SHIFT);
 	
-	nodesize 	= nodemem[nid].end - nodemem[nid].start ;
+	nodesize 	= nodemem[nid].end - start ;
 	numpfn 		= nodesize >> PAGE_SHIFT;
 
-	bank0size 	= nodemem[nid].hole[0] - nodemem[nid].start ;
+	bank0size 	= nodemem[nid].hole[0] - start ;
 	/* If nid == master node && no kernel text replication */
 	bank0size      -= 0xA00000 ;	/* Kernel text + stuff */
 	bank0size      -= ((numpfn + 7) >> 3);
@@ -163,198 +158,198 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 
-extern bootmem_data_t 	bdata[] ;
-static int	 	curnodeid ;
+extern bootmem_data_t bdata[];
 
+/*
+ * This assumes there will be a hole in kernel-usable memory between nodes
+ * (due to prom). The memory descriptors invoked via efi_memmap_walk are 
+ * in increasing order. It tries to identify first suitable free area to 
+ * put the bootmem for the node in. When presented with the md holding
+ * the kernel, it only searches at the end of the kernel area.
+ */
 static int __init
-setup_node_bootmem(unsigned long start, unsigned long end, unsigned long nodefree)
+find_node_bootmem(unsigned long start, unsigned long end, void *arg)
 {
+	int nasid = GetNasId(__pa(start));
+	int cnodeid = NASID_TO_CNODEID(nasid);
+	unsigned long nodesize;
 	extern char _end;
-	int i;
-	unsigned long kernelend = PAGE_ALIGN((unsigned long)(&_end));
-	unsigned long pkernelend = __pa(kernelend);
-	unsigned long bootmap_start, bootmap_size;
-	unsigned long pstart, pend;
-
-	pstart = __pa(start) ;
-	pend   = __pa(end) ;
-
-	/* If we are past a node mem boundary, on simulated dig numa
-	 * increment current node id. */
-
-	curnodeid = NASID_TO_CNODEID(GetNasId(pstart)) ;
-
-       /*
-        * Make sure we are being passed page aligned addresses.
-        */
-	if ((start & (PAGE_SIZE - 1)) || (end & (PAGE_SIZE - 1)))
-               panic("setup_node_bootmem:align");
+	unsigned long kaddr = (unsigned long)&_end;
 
-
-	/* For now, just go to the lower CHUNK alignment so that 
-	 * chunktonid of 0-8MB and other lower mem pages get initted. */
-
-	pstart &= CHUNKMASK ;
-	pend = (pend+CHUNKSZ-1) & CHUNKMASK;
-
-	/* If pend == 0, both addrs below 8 MB, special case it
-	 * FIX: CHUNKNUM(pend-1) broken if pend == 0 
-	 * both addrs within 8MB */
-
-	if (pend == 0) {
-		chunktonid[0] = 0;
-		return 0;
-	}
-
-	/* Fill up the chunktonid array first. */
-
-        for (i = PCHUNKNUM(pstart); i <= PCHUNKNUM(pend-1); i++)
-               chunktonid[i] = curnodeid;
-
-	/* This check is bogus for now till MAXCHUNKS is properly
-	 * defined to say if it includes holes or not. */
-
-	if ((CHUNKTONID(PCHUNKNUM(pend)) > MAXCHUNKS) || 
-		(PCHUNKNUM(pstart) >= PCHUNKNUM(pend))) {
-		printk("Ign 0x%lx-0x%lx, ", __pa(start), __pa(end));
+	/*
+	 * Track memory available to kernel.
+	 */
+	nodemem[cnodeid].mtot += ((end - start) >> PAGE_SHIFT);
+	if (nodemem[cnodeid].done != DONE_NOTHING)
 		return(0);
-	}
+	nodesize = nodemem[cnodeid].end - ((nodemem[cnodeid].start >> 
+				SN1_NODE_ADDR_SHIFT) << SN1_NODE_ADDR_SHIFT);
+	nodesize >>= PAGE_SHIFT;
 
-	/* This routine gets called many times in node 0.
-	 * The first one to reach here would be the one after
-	 * kernelend to end of first node. */
-
-	NODE_DATA(curnodeid)->bdata = &(bdata[curnodeid]);
-
-	if (curnodeid == 0) {
-		/* for master node, forcibly assign these values
-		 * This gets called many times on dig but we
-		 * want these exact values 
-		 * Also on softsdv, the memdesc for 0 is missing */
-		NODE_START(curnodeid) = PAGE_OFFSET;
-		NODE_SIZE(curnodeid) = (end - PAGE_OFFSET);
-	} else {
-		/* This gets called only once for non zero nodes
-		 * If it does not, then NODE_STARt should be 
-		 * LOCAL_BASE(nid) */
+	/*
+	 * Adjust limits for the md holding the kernel.
+	 */
+	if ((start < kaddr) && (end > kaddr))
+		start = PAGE_ALIGN(kaddr);
 
-		NODE_START(curnodeid) = start;
-		NODE_SIZE(curnodeid) = (end - start);
+	/*
+	 * We need space for mem_map, bootmem map plus a few more pages
+	 * to satisfy alloc_bootmems out of node 0.
+	 */
+	if ((end - start) > ((nodesize * sizeof(struct page)) + (nodesize/8)
+						+ (10 * PAGE_SIZE))) {
+		nodemem[cnodeid].bstart = start;
+		nodemem[cnodeid].done = DONE_FINDING;
 	}
+	return(0);
+}
 
-	/* if end < kernelend do not do anything below this */
-	if (pend < pkernelend)
-		return 0 ;
+/*
+ * This assumes there will be a hole in kernel-usable memory between nodes
+ * (due to prom). The memory descriptors invoked via efi_memmap_walk are 
+ * in increasing order.
+ */
+static int __init
+build_node_bootmem(unsigned long start, unsigned long end, void *arg)
+{
+	int nasid = GetNasId(__pa(start));
+	int curnodeid = NASID_TO_CNODEID(nasid);
+	int i;
+	unsigned long pstart, pend;
+	extern char _end, _stext;
+	unsigned long kaddr = (unsigned long)&_end;
 
-       /*
-        * Handle the node that contains kernel text/data. It would
-        * be nice if the loader loads the kernel at a "chunk", ie
-        * not in memory that the kernel will ignore (else free_initmem
-        * has to worry about not freeing memory that the kernel ignores).
-        * Note that we assume the space from the node start to
-        * KERNEL_START can not hold all the bootmem data, but from kernel
-        * end to node end can.
-        */
-
-	/* TBD: This may be bogus in light of the above check. */
-
-	if ((pstart < pkernelend) && (pend >= pkernelend)) {
-               bootmap_start = pkernelend;
-	} else {
-               bootmap_start = __pa(start);    /* chunk & page aligned */
+	if (nodemem[curnodeid].done == DONE_FINDING) {
+		/*
+		 * This is where we come to know the node is present.
+		 * Do node wide tasks.
+		 */
+		nodemem[curnodeid].done = DONE_BUILDING;
+		NODE_DATA(curnodeid)->bdata = &(bdata[curnodeid]);
+
+		/*
+	 	 * Update the chunktonid array as a node wide task. There
+		 * are too many smalls mds on first node to do this per md.
+	 	 */
+		pstart = __pa(nodemem[curnodeid].start);
+		pend = __pa(nodemem[curnodeid].end);
+		pstart &= CHUNKMASK;
+		pend = (pend + CHUNKSZ - 1) & CHUNKMASK;
+		/* Possible check point to enforce minimum node size */
+		if (nodemem[curnodeid].bstart == -1) {
+			printk("No valid bootmem area on node %d\n", curnodeid);
+			while(1);
+		}
+		for (i = PCHUNKNUM(pstart); i <= PCHUNKNUM(pend - 1); i++)
+			chunktonid[i] = curnodeid;
+		if ((CHUNKTONID(PCHUNKNUM(pend)) > MAXCHUNKS) || 
+				(PCHUNKNUM(pstart) >= PCHUNKNUM(pend))) {
+			printk("Ign 0x%lx-0x%lx, ", __pa(start), __pa(end));
+			return(0);
+		}
+
+		/*
+		 * NODE_START and NODE_SIZE determine the physical range
+		 * on the node that mem_map array needs to be set up for.
+		 */
+		NODE_START(curnodeid) = ((nodemem[curnodeid].start >> 
+				SN1_NODE_ADDR_SHIFT) << SN1_NODE_ADDR_SHIFT);
+		NODE_SIZE(curnodeid) = (nodemem[curnodeid].end - 
+							NODE_START(curnodeid));
+
+        	nodemem[curnodeid].bsize = 
+			init_bootmem_node(NODE_DATA(curnodeid),
+			(__pa(nodemem[curnodeid].bstart) >> PAGE_SHIFT),
+			(__pa((nodemem[curnodeid].start >> SN1_NODE_ADDR_SHIFT)
+			<< SN1_NODE_ADDR_SHIFT) >> PAGE_SHIFT),
+			(__pa(nodemem[curnodeid].end) >> PAGE_SHIFT));
+
+	} else if (nodemem[curnodeid].done == DONE_NOTHING) {
+		printk("build_node_bootmem: node %d weirdness\n", curnodeid);
+		while(1);		/* Paranoia */
 	}
 
 	/*
-	 * Low memory is reserved for PROM use on SN1. The current node
-	 * memory model is [PROM mem ... kernel ... free], where the 
-	 * first two components are optional on a node.
+	 * Free the entire md.
 	 */
-	if (bootmap_start < __pa(nodefree))
-		bootmap_start = __pa(nodefree);
-
-/* XXX TBD */
-/* For curnodeid of 0, this gets called many times because of many
- * < 8MB segments. start gets bumped each time. We want to fix it
- * to 0 now. 
- */
-	if (curnodeid == 0)
-		start=PAGE_OFFSET;
-/*
- * This makes sure that in free_area_init_core - paging_init
- * idx is the entire node page range and for loop goes thro
- * all pages. test_bit for kernel pages should remain reserved
- * because free available mem takes care of kernel_start and end
- */
-
-        bootmap_size = init_bootmem_node(NODE_DATA(curnodeid),
-			(bootmap_start >> PAGE_SHIFT),
-			(__pa(start) >> PAGE_SHIFT), (__pa(end) >> PAGE_SHIFT));
+	free_bootmem_node(NODE_DATA(curnodeid), __pa(start), (end - start));
 
-	free_bootmem_node(NODE_DATA(curnodeid), bootmap_start + bootmap_size,
-				__pa(end) - (bootmap_start + bootmap_size));
+	/*
+	 * Reclaim back the bootmap and kernel areas.
+	 */
+	if ((start <= nodemem[curnodeid].bstart) && (end >
+						nodemem[curnodeid].bstart))
+		reserve_bootmem_node(NODE_DATA(curnodeid),
+		    __pa(nodemem[curnodeid].bstart), nodemem[curnodeid].bsize);
+	if ((start <= kaddr) && (end > kaddr))
+		reserve_bootmem_node(NODE_DATA(curnodeid),
+		    __pa(&_stext), (&_end - &_stext));
 
 	return(0);
 }
 
-void
+void __init
 setup_sn1_bootmem(int maxnodes)
 {
         int     i;
 
-        for (i=0;i<MAXNODES;i++) {
-                nodemem[i].usable = nodemem[i].start = -1 ;
-                nodemem[i].end   = 0 ;
-		memset(&nodemem[i].hole, -1, sizeof(nodemem[i].hole)) ;
+        for (i = 0; i < MAXNODES; i++) {
+                nodemem[i].start = nodemem[i].bstart = -1;
+                nodemem[i].end = nodemem[i].bsize = nodemem[i].mtot = 0;
+		nodemem[i].done = DONE_NOTHING;
+		memset(&nodemem[i].hole, -1, sizeof(nodemem[i].hole));
         }
-        efi_memmap_walk(build_nodemem_map, 0) ;
+        efi_memmap_walk(build_nodemem_map, 0);
 
-	/*
-	 * Run thru all the nodes, adjusting their starts. This is needed
-	 * because efi_memmap_walk() might not process certain mds that 
-	 * are marked reserved for PROM at node low memory.
-	 */
-	for (i = 0; i < maxnodes; i++)
-		nodemem[i].start = ((nodemem[i].start >> SN1_NODE_ADDR_SHIFT) <<
-					SN1_NODE_ADDR_SHIFT);
-	nodemem_valid = 1 ;
+	nodemem_valid = 1;
 
-	/* After building the nodemem map, check if the page table
+	/* 
+	 * After building the nodemem map, check if the node memmap
 	 * will fit in the first bank of each node. If not change
-	 * the node end addr till it fits. We dont want to do this
-	 * in mm/page_alloc.c
+	 * the node end addr till it fits.
  	 */
 
-        for (i=0;i<maxnodes;i++)
-		check_pgtbl_size(i) ;
-
-        for (i=0;i<maxnodes;i++)
-                setup_node_bootmem(nodemem[i].start, nodemem[i].end, nodemem[i].usable);
+        for (i = 0; i < maxnodes; i++)
+		check_pgtbl_size(i);
 
-	/*
-	 * Mark the holes as reserved, so the corresponding mem_map
-	 * entries will not be marked allocatable in free_all_bootmem*().
-	 */
-	for (i = 0; i < maxnodes; i++) {
-		int j = 0 ;
-		u64 holestart = -1 ;
-
-		do {
-			holestart = nodemem[i].hole[j++];
-			while ((j < SN1_MAX_BANK_PER_NODE) && 
-					(nodemem[i].hole[j] == (u64)-1))
-				j++;
-			if (j < SN1_MAX_BANK_PER_NODE)
-				reserve_bootmem_node(NODE_DATA(i), 
-					__pa(holestart), (nodemem[i].start + 
-					((long)j <<  SN1_BANK_ADDR_SHIFT) - 
-					 holestart));
-		} while (j < SN1_MAX_BANK_PER_NODE);
-	}
+	dump_nodemem_map(maxnodes);
 
-	dump_nodemem_map(maxnodes) ;
+	efi_memmap_walk(find_node_bootmem, 0);
+	efi_memmap_walk(build_node_bootmem, 0);
 }
 #endif
 
+void __init
+discontig_paging_init(void)
+{
+	int i;
+	unsigned long max_dma, zones_size[MAX_NR_ZONES], holes_size[MAX_NR_ZONES];
+	extern void dump_node_data(void);
+
+	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+	for (i = 0; i < numnodes; i++) {
+		unsigned long startpfn = __pa((void *)NODE_START(i)) >> PAGE_SHIFT;
+		unsigned long numpfn = NODE_SIZE(i) >> PAGE_SHIFT;
+		memset(zones_size, 0, sizeof(zones_size));
+		memset(holes_size, 0, sizeof(holes_size));
+		holes_size[ZONE_DMA] = numpfn - nodemem[i].mtot;
+
+		if ((startpfn + numpfn) < max_dma) {
+			zones_size[ZONE_DMA] = numpfn;
+		} else if (startpfn > max_dma) {
+			zones_size[ZONE_NORMAL] = numpfn;
+			panic("discontig_paging_init: %d\n", i);
+		} else {
+			zones_size[ZONE_DMA] = (max_dma - startpfn);
+			zones_size[ZONE_NORMAL] = numpfn - zones_size[ZONE_DMA];
+			panic("discontig_paging_init: %d\n", i);
+		}
+		free_area_init_node(i, NODE_DATA(i), NULL, zones_size, startpfn<<PAGE_SHIFT, holes_size);
+		free_unused_memmap_node(i);
+	}
+	dump_node_data();
+}
+
 /*
  * This used to be invoked from an SN1 specific hack in efi_memmap_walk.
  * It tries to ignore banks which the kernel is ignoring because bank 0 
@@ -386,10 +381,10 @@
 	int	i,j;
 
         printk("NODEMEM_S info ....\n") ;
-        printk("Node         start                end                 usable\n");
+        printk("Node         start                end\n");
         for (i=0;i<maxnodes;i++) {
-                printk("%d      0x%lx   0x%lx   0x%lx\n",
-                       i, nodemem[i].start, nodemem[i].end, nodemem[i].usable);
+                printk("%d      0x%lx   0x%lx\n",
+                       i, nodemem[i].start, nodemem[i].end);
                 printk("Holes -> ") ;
                 for (j=0;j<SN1_MAX_BANK_PER_NODE;j++)
                         printk("0x%lx ", nodemem[i].hole[j]) ;
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/probe.c linux/arch/ia64/sn/sn1/probe.c
--- v2.4.3/linux/arch/ia64/sn/sn1/probe.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/sn1/probe.c	Thu Apr  5 12:51:47 2001
@@ -0,0 +1,62 @@
+/*
+ * Platform dependent support for IO probing.
+ *
+ * Copyright (C) 2000   Silicon Graphics
+ * Copyright (C) 2000   Jack Steiner (steiner@sgi.com)
+ */
+
+#include <asm/sn/sn_sal.h>
+
+/*
+ * ia64_sn_probe_io_slot
+ *	This function will probe a physical address to determine if
+ *	the address can be read. If reading the address causes a BUS
+ *	error, an error is returned. If the probe succeeds, the contents 
+ *	of the memory location is returned.
+ *
+ *   Calling sequence:
+ *		ia64_probe_io_slot(paddr, size, data_ptr)
+ *
+ *   Input:
+ *	paddr		Physical address to probe
+ *	size		Number bytes to read (1,2,4,8)
+ *	data_ptr	Address to store value read by probe
+ *		          (-1 returned if probe fails)
+ *
+ *   Output:
+ *	Status
+ *		 0 - probe successful
+ *		 1 - probe failed (generated MCA)
+ *		 2 - Bad arg
+ *		<0 - PAL error
+ */
+
+
+u64
+ia64_sn_probe_io_slot(long paddr, long size, void *data_ptr)
+{
+	struct ia64_sal_retval isrv;
+
+	SAL_CALL(isrv, SN_SAL_PROBE, paddr, size, 0, 0, 0, 0, 0);
+
+	if (data_ptr) {
+		switch (size) {
+			case 1:
+				*((u8*)data_ptr) = (u8)isrv.v0;
+				break;
+			case 2:
+				*((u16*)data_ptr) = (u16)isrv.v0;
+				break;
+			case 4:
+				*((u32*)data_ptr) = (u32)isrv.v0;
+				break;
+			case 8:
+				*((u64*)data_ptr) = (u64)isrv.v0;
+				break;
+			default:
+				isrv.status = 2;	
+		}
+	}
+
+	return isrv.status;
+}
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/setup.c linux/arch/ia64/sn/sn1/setup.c
--- v2.4.3/linux/arch/ia64/sn/sn1/setup.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/sn1/setup.c	Thu Apr  5 12:51:47 2001
@@ -15,12 +15,30 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
+#include <linux/serial.h>
 
 #include <asm/sn/mmzone_sn1.h>
 #include <asm/io.h>
+#include <asm/dma.h>
 #include <asm/machvec.h>
 #include <asm/system.h>
 #include <asm/processor.h>
+#include <asm-ia64/sn/arch.h>
+#include <asm-ia64/sn/addrs.h>
+
+
+/*
+ * This is the address of the RRegs in the HSpace of the global
+ * master.  It is used by a hack in serial.c (serial_[in|out],
+ * printk.c (early_printk), and kdb_io.c to put console output on that
+ * node's Bedrock UART.  It is initialized here to 0, so that
+ * early_printk won't try to access the UART before
+ * master_node_bedrock_address is properly calculated.
+ */
+u64 master_node_bedrock_address = 0UL;
+
+static void sn_fix_ivt_for_partitioned_system(void);
+
 
 /*
  * The format of "screen_info" is strange, and due to early i386-setup
@@ -58,31 +76,169 @@
 #endif
 }
 
+#if defined(BRINGUP) && defined(CONFIG_IA64_EARLY_PRINTK)
+void __init
+early_sn1_setup(void)
+{
+	master_node_bedrock_address = 
+		(u64)REMOTE_HSPEC_ADDR(get_nasid(), 0);
+	printk("early_sn1_setup: setting master_node_bedrock_address to 0x%lx\n", master_node_bedrock_address);
+}
+#endif /* BRINGUP && CONFIG_IA64_EARLY_PRINTK */
+
 void __init
 sn1_setup(char **cmdline_p)
 {
-	extern void init_sn1_smp_config(void);
+#if defined(CONFIG_SERIAL) && !defined(CONFIG_SERIAL_SGI_L1_PROTOCOL)
+	struct serial_struct req;
+#endif
+
+	MAX_DMA_ADDRESS = PAGE_OFFSET + 0x10000000000UL;
+	master_node_bedrock_address = 
+		(u64)REMOTE_HSPEC_ADDR(get_nasid(), 0);
+	printk("sn1_setup: setting master_node_bedrock_address to 0x%lx\n",
+		   master_node_bedrock_address);
+
+#if defined(CONFIG_SERIAL) && !defined(CONFIG_SERIAL_SGI_L1_PROTOCOL)
+	/*
+	 * We do early_serial_setup() to clean out the rs-table[] from the
+	 * statically compiled in version.
+	 */
+	memset(&req, 0, sizeof(struct serial_struct));
+	req.line = 0;
+	req.baud_base = 124800;
+	req.port = 0;
+	req.port_high = 0;
+	req.irq = 0;
+	req.flags = (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST);
+	req.io_type = SERIAL_IO_MEM;
+	req.hub6 = 0;
+	req.iomem_base = (u8 *)(master_node_bedrock_address + 0x80);
+	req.iomem_reg_shift = 3;
+	req.type = 0;
+	req.xmit_fifo_size = 0;
+	req.custom_divisor = 0;
+	req.closing_wait = 0;
+	early_serial_setup(&req);
+#endif /* CONFIG_SERIAL && !CONFIG_SERIAL_SGI_L1_PROTOCOL */
+
 	ROOT_DEV = to_kdev_t(0x0301);		/* default to first IDE drive */
+	sn_fix_ivt_for_partitioned_system();
 
-	init_sn1_smp_config();
-#ifdef ZZZ
-#if !defined (CONFIG_IA64_SOFTSDV_HACKS)
-        /*
-         * Program the timer to deliver timer ticks.  0x40 is the I/O port
-         * address of PIT counter 0, 0x43 is the I/O port address of the
-         * PIT control word.
-         */
-        request_region(0x40,0x20,"timer");
-        outb(0x34, 0x43);            /* Control word */
-        outb(LATCH & 0xff , 0x40);   /* LSB */
-        outb(LATCH >> 8, 0x40);      /* MSB */
-        printk("PIT: LATCH at 0x%x%x for %d HZ\n", LATCH >> 8, LATCH & 0xff, HZ);
-#endif
-#endif
 #ifdef CONFIG_SMP
 	init_smp_config();
 #endif
 	screen_info = sn1_screen_info;
+}
+
+
+/* 
+ * sn_fix_ivt_for_partitioned_system
+ *
+ * This is an ugly hack that is needed for partitioned systems.
+ *
+ * On a partitioned system, most partitions do NOT have a physical address 0.
+ * Unfortunately, the exception handling code in ivt.S has a couple of physical
+ * addresses of kernel structures hardcoded into "movl" instructions.
+ * These addresses are correct on partition 0 only. On all other partitions,
+ * the addresses must be changed to reference the correct address.
+ *
+ * This routine scans the ivt code and replaces the hardcoded addresses with 
+ * the correct address.
+ *
+ * Note that we could have made the ivt.S code dynamically determine the correct
+ * address but this would add code to performance critical pathes. This option
+ * was rejected.
+ */
+
+#define TEMP_mlx	4		/* template type that contains movl instruction */
+#define TEMP_mlX	5		/* template type that contains movl instruction */
+
+typedef union {				/* Instruction encoding for movl instruction */
+	struct {
+		unsigned long	qp:6;
+		unsigned long	r1:7;
+		unsigned long	imm7b:7;
+		unsigned long	vc:1;
+		unsigned long	ic:1;
+		unsigned long	imm5c:5;
+		unsigned long	imm9d:9;
+		unsigned long	i:1;
+		unsigned long	op:4;
+		unsigned long	fill:23;
+	} b;
+	unsigned long	l;
+} movl_instruction_t;
+
+#define MOVL_OPCODE	6
+#define MOVL_ARG(a,b)	(((long)a.i<<63) | ((long)b<<22) | ((long)a.ic<<21) | \
+			((long)a.imm5c<<16) | ((long)a.imm9d<<7) | ((long)a.imm7b))
+
+typedef struct {				/* Instruction bundle */
+	unsigned long template:5;
+	unsigned long ins2:41;
+	unsigned long ins1l:18;
+	unsigned long ins1u:23;
+	unsigned long ins0:41;
+} instruction_bundle_t;
+
+
+static void __init
+sn_fix_ivt_for_partitioned_system(void)
+{
+	extern int		ia64_ivt;
+	instruction_bundle_t	*p, *pend;
+	movl_instruction_t	ins0, ins1, ins2;
+	long			new_ins1, phys_offset;
+	unsigned long		val;
+
+	/*
+	 * Setup to scan the ivt code.
+	 */
+	p = (instruction_bundle_t*)&ia64_ivt;
+	pend = p + 0x8000/sizeof(instruction_bundle_t);
+	phys_offset = __pa(p) & ~0x1ffffffffUL;
+
+	/*
+	 * Hunt for movl instructions that contain the node 0 physical address 
+	 * of "SWAPPER_PGD_ADDR".  These addresses must be relocated to reference the 
+	 * actual node that the kernel is loaded on.
+	 */
+	for (; p < pend; p++) {
+		if (p->template != TEMP_mlx && p->template != TEMP_mlX)
+			continue;
+		ins0.l =  p->ins0;
+		if (ins0.b.op != MOVL_OPCODE)
+			continue;
+		ins1.l =  ((long)p->ins1u<<18) | p->ins1l;
+		ins2.l =  p->ins2;
+		val = MOVL_ARG(ins0.b, ins1.l);
+
+		/*
+		 * Test for correct address. SWAPPER_PGD_ADDR will
+		 * always be a node 0 virtual address. Note that we cant
+		 * use the __pa or __va macros here since they may contain
+		 * debug code that gets fooled here.
+		 */
+		if ((PAGE_OFFSET | val)  != SWAPPER_PGD_ADDR)
+			continue;
+
+		/*
+		 * We found an instruction that needs to be fixed. The following
+		 * inserts the NASID of the ivt into the movl instruction.
+		 */
+		new_ins1 = ins1.l | (phys_offset>>22);
+		p->ins1l = new_ins1 & 0x3ffff;
+		p->ins1u = (new_ins1>>18) & 0x7fffff;
+		ia64_fc(p);
+	}
+
+	/*
+	 * Do necessary serialization.
+	 */
+	ia64_sync_i();
+	ia64_srlz_i();
+
 }
 
 int
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/smp.c linux/arch/ia64/sn/sn1/smp.c
--- v2.4.3/linux/arch/ia64/sn/sn1/smp.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/sn1/smp.c	Thu Apr  5 12:51:47 2001
@@ -124,10 +124,10 @@
 
 #ifdef CONFIG_SMP
 
+#ifdef PTC_NOTYET
 static void __init
 process_sal_ptc_domain_info(ia64_sal_ptc_domain_info_t *di, int domain)
 {
-#ifdef PTC_NOTYET
 	ia64_sal_ptc_domain_proc_entry_t	*pe;
 	int 					i, sapicid, cpuid;
 
@@ -138,7 +138,6 @@
 		sn_sapicid_info[cpuid].domain = domain;
 		sn_sapicid_info[cpuid].sapicid = sapicid;
 	}
-#endif
 }
 
 
@@ -153,6 +152,7 @@
 		process_sal_ptc_domain_info(di, i);	
 	}
 }
+#endif
 
 
 void __init
@@ -179,7 +179,7 @@
 {
 
 #ifdef PTC_NOTYET
-	sn_sapicid_info[0].sapicid = hard_processor_sapicid();
+	sn_sapicid_info[0].sapicid = hard_smp_processor_id();
 #endif
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/sn1_asm.S linux/arch/ia64/sn/sn1/sn1_asm.S
--- v2.4.3/linux/arch/ia64/sn/sn1/sn1_asm.S	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/sn1/sn1_asm.S	Thu Apr  5 12:51:47 2001
@@ -4,3 +4,146 @@
  * Copyright (C) 2000 Jack Steiner (steiner@sgi.com)
  */
 
+#include <linux/config.h>
+#ifdef CONFIG_IA64_SGI_AUTOTEST
+
+// Testing only.
+// Routine will cause MCAs
+//   zzzmsa(n)
+//      n=0 MCA via duplicate TLB dropin
+//      n=0 MCA via read of garbage address
+//
+
+#define ITIR(key, ps)           ((key<<8) | (ps<<2))
+#define TLB_PAGESIZE            28                      // Use 256MB pages for now.
+
+                        .global zzzmca
+                        .proc   zzzmca
+zzzmca:
+                        alloc   loc4       = ar.pfs,2,8,1,0;;
+                        cmp.ne  p6,p0=r32,r0;;
+                        movl    r2=0x2dead
+                        movl    r3=0x3dead
+                        movl    r15=0x15dead
+                        movl    r16=0x16dead
+                        movl    r31=0x31dead
+                        movl    loc0=0x34beef
+                        movl    loc1=0x35beef
+                        movl    loc2=0x36beef
+                        movl    loc3=0x37beef
+                        movl    out0=0x42beef
+
+                        movl    r20=0x32feed;;
+                        mov     ar32=r20
+                        movl    r20=0x36feed;;
+                        mov     ar36=r20
+                        movl    r20=0x65feed;;
+                        mov     ar65=r20
+                        movl    r20=0x66feed;;
+                        mov     ar66=r20
+
+(p6)                    br.cond.sptk    1f
+
+                        rsm      0x2000;;
+                        srlz.d;
+                        mov      r11      = 1
+                        mov      r3       = ITIR(0,TLB_PAGESIZE);;
+                        mov      cr.itir  = r3
+                        mov      r10      = 0;;
+                        itr.d    dtr[r11] = r10;;
+                        mov      r11      = 2
+
+                        itr.d    dtr[r11] = r10;;
+                        br      9f
+
+1:                      movl    r8=0xfe00000048;;
+                        ld8     r9=[r8];;
+                        mf
+                        mf.a
+                        srlz.d
+
+9:                      mov     ar.pfs=loc4
+                        br.ret.sptk     rp
+
+                        .endp   zzzmca
+
+                        .global zzzspec
+                        .proc   zzzspec
+zzzspec:
+			mov	r8=r32
+			movl	r9=0xe000000000000000
+			movl	r10=0x4000;;
+			ld8.s	r16=[r8];;
+			ld8.s	r17=[r9];;
+			add	r8=r8,r10;;
+			ld8.s	r18=[r8];;
+			add	r8=r8,r10;;
+			ld8.s	r19=[r8];;
+			add	r8=r8,r10;;
+			ld8.s	r20=[r8];;
+			mov	r8=r0
+			tnat.nz	p6,p0=r16
+			tnat.nz	p7,p0=r17
+			tnat.nz	p8,p0=r18
+			tnat.nz	p9,p0=r19
+			tnat.nz	p10,p0=r20;;
+		(p6)	dep	r8=-1,r8,0,1;;
+		(p7)	dep	r8=-1,r8,1,1;;
+		(p8)	dep	r8=-1,r8,2,1;;
+		(p9)	dep	r8=-1,r8,3,1;;
+		(p10)	dep	r8=-1,r8,4,1;;
+                        br.ret.sptk     rp
+                        .endp   zzzspec
+
+                        .global zzzspec2
+                        .proc   zzzspec2
+zzzspec2:
+			cmp.eq	p6,p7=r2,r2
+			movl	r16=0xc0000a0001000020
+			;;
+			mf
+			;;
+			ld8	r9=[r16]
+		(p6)	br.spnt	1f
+			ld8	r10=[r32]
+			;;
+		1:	mf.a
+			mf
+
+			ld8	r9=[r16];;
+			cmp.ne	p6,p7=r9,r16
+		(p6)	br.spnt	1f
+			ld8	r10=[r32]
+			;;
+		1:	mf.a
+			mf
+
+			ld8	r9=[r33];;
+			cmp.ne	p6,p7=r9,r33
+		(p6)	br.spnt	1f
+			ld8	r10=[r32]
+			;;
+		1:	mf.a
+			mf
+
+			tpa	r23=r32
+			add	r20=512,r33
+			add	r21=1024,r33;;
+			ld8	r9=[r20]
+			ld8	r10=[r21];;
+			nop.i	0
+			{ .mib
+			nop.m 0
+			cmp.ne	p6,p7=r10,r33
+		(p6)	br.spnt	1f
+			}
+			ld8	r10=[r32]
+			;;
+		1:	mf.a
+			mf
+			br.ret.sptk     rp
+
+                        .endp   zzzspec
+
+#endif
+
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/sn1_ksyms.c linux/arch/ia64/sn/sn1/sn1_ksyms.c
--- v2.4.3/linux/arch/ia64/sn/sn1/sn1_ksyms.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/sn1/sn1_ksyms.c	Thu Apr  5 12:51:47 2001
@@ -0,0 +1,39 @@
+/* 
+ * 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 Silicon Graphics, Inc.
+ * Copyright (C) 2000 Jesse Barnes (jbarnes@sgi.com)
+ */
+
+
+/*
+ * Architecture-specific kernel symbols
+ */
+
+#include <linux/module.h>
+
+#include <asm/machvec.h>
+
+/*
+ * I/O routines
+ */
+EXPORT_SYMBOL(sn1_outb);
+EXPORT_SYMBOL(sn1_outl);
+EXPORT_SYMBOL(sn1_outw);
+EXPORT_SYMBOL(sn1_inw);
+EXPORT_SYMBOL(sn1_inb);
+EXPORT_SYMBOL(sn1_inl);
+
+/*
+ * other stuff (more to be added later, cleanup then)
+ */
+EXPORT_SYMBOL(sn1_pci_map_sg);
+EXPORT_SYMBOL(sn1_pci_unmap_sg);
+EXPORT_SYMBOL(sn1_pci_alloc_consistent);
+EXPORT_SYMBOL(sn1_pci_free_consistent);
+EXPORT_SYMBOL(sn1_dma_address);
+
+#include <linux/mm.h>
+EXPORT_SYMBOL(alloc_pages);
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/sv.c linux/arch/ia64/sn/sn1/sv.c
--- v2.4.3/linux/arch/ia64/sn/sn1/sv.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/sn1/sv.c	Thu Apr  5 12:51:47 2001
@@ -0,0 +1,551 @@
+/*
+ * 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 Silicon Graphics, Inc.  All rights reserved
+ *
+ * This implemenation of synchronization variables is heavily based on
+ * one done by Steve Lord <lord@sgi.com>
+ *
+ * Paul Cassella <pwc@sgi.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/semaphore.h>
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+#include <asm/current.h>
+
+#include <asm/sn/sv.h>
+
+/* Define this to have sv_test() run some simple tests.
+   kernel_thread() must behave as expected when this is called.  */
+#undef RUN_SV_TEST
+
+#define DEBUG
+
+/* Set up some macros so sv_wait(), sv_signal(), and sv_broadcast()
+   can sanity check interrupt state on architectures where we know
+   how. */
+#ifdef DEBUG
+ #define SV_DEBUG_INTERRUPT_STATE
+ #ifdef __mips64
+  #define SV_TEST_INTERRUPTS_ENABLED(flags) ((flags & 0x1) != 0)
+  #define SV_TEST_INTERRUPTS_DISABLED(flags) ((flags & 0x1) == 0)
+  #define SV_INTERRUPT_TEST_WORKERS 31
+ #elif defined(__ia64)
+  #define SV_TEST_INTERRUPTS_ENABLED(flags) ((flags & 0x4000) != 0)
+  #define SV_TEST_INTERRUPTS_DISABLED(flags) ((flags & 0x4000) == 0)
+  #define SV_INTERRUPT_TEST_WORKERS 4 /* simulator's slow */
+ #else
+  #undef  SV_DEBUG_INTERRUPT_STATE
+  #define SV_INTERRUPT_TEST_WORKERS 4 /* reasonable? default. */
+ #endif /* __mips64 */
+#endif /* DEBUG */
+
+
+/* XXX FIXME hack hack hack.  Our mips64 tree is from before the
+   switch to WQ_FLAG_EXCLUSIVE, and our ia64 tree is from after it. */
+#ifdef TASK_EXCLUSIVE
+  #undef EXCLUSIVE_IN_QUEUE
+#else
+  #define EXCLUSIVE_IN_QUEUE
+  #define TASK_EXCLUSIVE 0 /* for the set_current_state() in sv_wait() */
+#endif
+
+
+static inline void sv_lock(sv_t *sv) {
+	spin_lock(&sv->sv_lock);
+}
+
+static inline void sv_unlock(sv_t *sv) {
+	spin_unlock(&sv->sv_lock);
+}
+
+/* up() is "extern inline", so we can't pass its address to sv_wait.
+   Use this function's address instead. */
+static void up_wrapper(struct semaphore *sem) {
+	up(sem);
+}
+
+/* spin_unlock() is sometimes a macro. */
+static void spin_unlock_wrapper(spinlock_t *s) {
+	spin_unlock(s);
+}
+
+/* XXX Perhaps sv_wait() should do the switch() each time and avoid
+   the extra indirection and the need for the _wrapper functions? */
+
+static inline void sv_set_mon_type(sv_t *sv, int type) {
+	switch (type) {
+	case SV_MON_SPIN:
+		sv->sv_mon_unlock_func =
+		  (sv_mon_unlock_func_t)spin_unlock_wrapper;
+		break;
+	case SV_MON_SEMA:
+		sv->sv_mon_unlock_func =
+		  (sv_mon_unlock_func_t)up_wrapper;
+		if(sv->sv_flags & SV_INTS) {
+			printk(KERN_ERR "sv_set_mon_type: The monitor lock "
+			       "cannot be shared with interrupts if it is a "
+			       "semaphore!\n");
+			BUG();
+		}
+		if(sv->sv_flags & SV_BHS) {
+			printk(KERN_ERR "sv_set_mon_type: The monitor lock "
+			       "cannot be shared with bottom-halves if it is "
+			       "a semaphore!\n");
+			BUG();
+		}
+		break;
+#if 0 
+	/*
+	 * If needed, and will need to think about interrupts.  This
+	 * may be needed, for example, if someone wants to use sv's
+	 * with something like dev_base; writers need to hold two
+	 * locks. 
+	 */
+	case SV_MON_CUSTOM: 
+		{
+		struct sv_mon_custom *c = lock;
+		sv->sv_mon_unlock_func = c->sv_mon_unlock_func;
+		sv->sv_mon_lock        = c->sv_mon_lock;
+		break;
+		}
+#endif
+		
+	default:
+		printk(KERN_ERR "sv_set_mon_type: unknown type %d (0x%x)! "
+		       "(flags 0x%x)\n", type, type, sv->sv_flags);
+		BUG();
+		break;
+	}
+	sv->sv_flags |= type;
+}
+
+static inline void sv_set_ord(sv_t *sv, int ord) {
+	if (!ord)
+		ord = SV_ORDER_DEFAULT;
+
+	if (ord != SV_ORDER_FIFO && ord != SV_ORDER_LIFO) {
+		printk(KERN_EMERG "sv_set_ord: unknown order %d (0x%x)! ",
+		       ord, ord);
+		BUG();
+	}
+
+	sv->sv_flags |= ord;
+}
+
+void sv_init(sv_t *sv, sv_mon_lock_t *lock, int flags) 
+{
+	int ord = flags & SV_ORDER_MASK;
+	int type = flags & SV_MON_MASK;
+
+	/* Copy all non-order, non-type flags */
+	sv->sv_flags = (flags & ~(SV_ORDER_MASK | SV_MON_MASK));
+
+	if((sv->sv_flags & (SV_INTS | SV_BHS)) == (SV_INTS | SV_BHS)) {
+	  printk(KERN_ERR "sv_init: do not set both SV_INTS and SV_BHS, only SV_INTS.\n");
+	  BUG();
+	}
+
+	sv_set_ord(sv, ord);
+	sv_set_mon_type(sv, type);
+
+	/* If lock is NULL, we'll get it from sv_wait_compat() (and
+           ignore it in sv_signal() and sv_broadcast()). */
+	sv->sv_mon_lock = lock;
+
+	spin_lock_init(&sv->sv_lock);
+	init_waitqueue_head(&sv->sv_waiters);
+}
+
+/*
+ * The associated lock must be locked on entry.  It is unlocked on return.
+ *
+ * Return values:
+ *
+ * n < 0 : interrupted,  -n jiffies remaining on timeout, or -1 if timeout == 0
+ * n = 0 : timeout expired
+ * n > 0 : sv_signal()'d, n jiffies remaining on timeout, or 1 if timeout == 0
+ */
+signed long sv_wait(sv_t *sv, int sv_wait_flags, unsigned long timeout) 
+{
+	DECLARE_WAITQUEUE( wait, current );
+	unsigned long flags;
+	signed long ret = 0;
+
+#ifdef SV_DEBUG_INTERRUPT_STATE
+	{
+	unsigned long flags;
+	__save_flags(flags);
+
+	if(sv->sv_flags & SV_INTS) {
+		if(SV_TEST_INTERRUPTS_ENABLED(flags)) {
+			printk(KERN_ERR "sv_wait: SV_INTS and interrupts "
+			       "enabled (flags: 0x%lx)\n", flags);
+			BUG();
+		}
+	} else {
+		if (SV_TEST_INTERRUPTS_DISABLED(flags)) {
+			printk(KERN_WARNING "sv_wait: !SV_INTS and interrupts "
+			       "disabled! (flags: 0x%lx)\n", flags);
+		}
+	}
+	}
+#endif  /* SV_DEBUG_INTERRUPT_STATE */
+
+	sv_lock(sv);
+
+	sv->sv_mon_unlock_func(sv->sv_mon_lock);
+
+	/* Add ourselves to the wait queue and set the state before
+	 * releasing the sv_lock so as to avoid racing with the
+	 * wake_up() in sv_signal() and sv_broadcast(). 
+	 */
+
+	/* don't need the _irqsave part, but there is no wq_write_lock() */
+	wq_write_lock_irqsave(&sv->sv_waiters.lock, flags);
+
+#ifdef EXCLUSIVE_IN_QUEUE
+	wait.flags |= WQ_FLAG_EXCLUSIVE;
+#endif
+
+	switch(sv->sv_flags & SV_ORDER_MASK) {
+	case SV_ORDER_FIFO:
+		__add_wait_queue_tail(&sv->sv_waiters, &wait);
+		break;
+	case SV_ORDER_FILO:
+		__add_wait_queue(&sv->sv_waiters, &wait);
+		break;
+	default:
+		printk(KERN_ERR "sv_wait: unknown order!  (sv: 0x%p, flags: 0x%x)\n",
+					sv, sv->sv_flags);
+		BUG();
+	}
+	wq_write_unlock_irqrestore(&sv->sv_waiters.lock, flags);
+
+	if(sv_wait_flags & SV_WAIT_SIG)
+		set_current_state(TASK_EXCLUSIVE | TASK_INTERRUPTIBLE  );
+	else
+		set_current_state(TASK_EXCLUSIVE | TASK_UNINTERRUPTIBLE);
+
+	spin_unlock(&sv->sv_lock);
+
+	if(sv->sv_flags & SV_INTS)
+		local_irq_enable();
+	else if(sv->sv_flags & SV_BHS)
+		local_bh_enable();
+
+	if (timeout)
+		ret = schedule_timeout(timeout);
+	else
+		schedule();
+
+	if(current->state != TASK_RUNNING) /* XXX Is this possible? */ {
+		printk(KERN_ERR "sv_wait: state not TASK_RUNNING after "
+		       "schedule().\n");
+		set_current_state(TASK_RUNNING);
+	}
+
+	remove_wait_queue(&sv->sv_waiters, &wait);
+
+	/* Return cases:
+	   - woken by a sv_signal/sv_broadcast
+	   - woken by a signal
+	   - woken by timeout expiring
+	*/
+
+	/* XXX This isn't really accurate; we may have been woken
+           before the signal anyway.... */
+	if(signal_pending(current))
+		return timeout ? -ret : -1;
+	return timeout ? ret : 1;
+}
+
+
+void sv_signal(sv_t *sv) 
+{
+	/* If interrupts can acquire this lock, they can also acquire the
+	   sv_mon_lock, which we must already have to have called this, so
+	   interrupts must be disabled already.  If interrupts cannot
+	   contend for this lock, we don't have to worry about it. */
+
+#ifdef SV_DEBUG_INTERRUPT_STATE
+	if(sv->sv_flags & SV_INTS) {
+		unsigned long flags;
+		__save_flags(flags);
+		if(SV_TEST_INTERRUPTS_ENABLED(flags))
+			printk(KERN_ERR "sv_signal: SV_INTS and "
+			"interrupts enabled! (flags: 0x%lx)\n", flags);
+	}
+#endif /* SV_DEBUG_INTERRUPT_STATE */
+
+	sv_lock(sv);
+	wake_up(&sv->sv_waiters);
+	sv_unlock(sv);
+}
+
+void sv_broadcast(sv_t *sv) 
+{
+#ifdef SV_DEBUG_INTERRUPT_STATE
+	if(sv->sv_flags & SV_INTS) {
+		unsigned long flags;
+		__save_flags(flags);
+		if(SV_TEST_INTERRUPTS_ENABLED(flags))
+			printk(KERN_ERR "sv_broadcast: SV_INTS and "
+			       "interrupts enabled! (flags: 0x%lx)\n", flags);
+	}
+#endif /* SV_DEBUG_INTERRUPT_STATE */
+
+	sv_lock(sv);
+	wake_up_all(&sv->sv_waiters);
+	sv_unlock(sv);
+}
+
+void sv_destroy(sv_t *sv) 
+{
+	if(!spin_trylock(&sv->sv_lock)) {
+		printk(KERN_ERR "sv_destroy: someone else has sv 0x%p locked!\n", sv);
+		BUG();
+	}
+
+	/* XXX Check that the waitqueue is empty? 
+	       Mark the sv destroyed?
+	*/
+}
+
+
+#ifdef RUN_SV_TEST
+
+static DECLARE_MUTEX_LOCKED(talkback);
+static DECLARE_MUTEX_LOCKED(sem);
+sv_t sv;
+sv_t sv_filo;
+
+static int sv_test_1_w(void *arg) 
+{
+	printk("sv_test_1_w: acquiring spinlock 0x%p...\n", arg);
+
+	spin_lock((spinlock_t*)arg);
+	printk("sv_test_1_w: spinlock acquired, waking sv_test_1_s.\n");
+
+	up(&sem);
+
+	printk("sv_test_1_w: sv_spin_wait()'ing.\n");
+
+	sv_spin_wait(&sv, arg);
+
+	printk("sv_test_1_w: talkback.\n");
+	up(&talkback);
+
+	printk("sv_test_1_w: exiting.\n");
+	return 0;
+}
+
+static int sv_test_1_s(void *arg) 
+{
+	printk("sv_test_1_s: waiting for semaphore.\n");
+	down(&sem);
+	printk("sv_test_1_s: semaphore acquired.  Acquiring spinlock.\n");
+	spin_lock((spinlock_t*)arg);
+	printk("sv_test_1_s: spinlock acquired.  sv_signaling.\n");
+	sv_signal(&sv);
+	printk("sv_test_1_s: talkback.\n");
+	up(&talkback);
+	printk("sv_test_1_s: exiting.\n");
+	return 0;
+
+}
+
+static int count;
+static DECLARE_MUTEX(monitor);
+
+static int sv_test_2_w(void *arg) 
+{
+	int dummy = count++;
+	sv_t *sv = (sv_t *)arg;
+
+	down(&monitor);
+	up(&talkback);
+	printk("sv_test_2_w: thread %d started, sv_waiting.\n", dummy);
+	sv_sema_wait(sv, &monitor);
+	printk("sv_test_2_w: thread %d woken, exiting.\n", dummy);
+	up(&sem);
+	return 0;
+}
+
+static int sv_test_2_s_1(void *arg) 
+{
+	int i;
+	sv_t *sv = (sv_t *)arg;
+
+	down(&monitor);
+	for(i = 0; i < 3; i++) {
+		printk("sv_test_2_s_1: waking one thread.\n");
+		sv_signal(sv);
+		down(&sem);
+	}
+
+	printk("sv_test_2_s_1: signaling and broadcasting again.  Nothing should happen.\n");
+	sv_signal(sv);
+	sv_broadcast(sv);
+	sv_signal(sv);
+	sv_broadcast(sv);
+
+	printk("sv_test_2_s_1: talkbacking.\n");
+	up(&talkback);
+	up(&monitor);
+	return 0;
+}
+
+static int sv_test_2_s(void *arg) 
+{
+	int i;
+	sv_t *sv = (sv_t *)arg;
+
+	down(&monitor);
+	for(i = 0; i < 3; i++) {
+		printk("sv_test_2_s: waking one thread (should be %d.)\n", i);
+		sv_signal(sv);
+		down(&sem);
+	}
+
+	printk("sv_test_3_s: waking remaining threads with broadcast.\n");
+	sv_broadcast(sv);
+	for(; i < 10; i++)
+		down(&sem);
+
+	printk("sv_test_3_s: sending talkback.\n");
+	up(&talkback);
+
+	printk("sv_test_3_s: exiting.\n");
+	up(&monitor);
+	return 0;
+}
+
+
+static void big_test(sv_t *sv) 
+{
+	int i;
+
+	count = 0;
+
+	for(i = 0; i < 3; i++) {
+		printk("big_test: spawning thread %d.\n", i);
+		kernel_thread(sv_test_2_w, sv, 0);
+		down(&talkback);
+	}
+
+	printk("big_test: spawning first wake-up thread.\n");
+	kernel_thread(sv_test_2_s_1, sv, 0);
+
+	down(&talkback);
+	printk("big_test: talkback happened.\n");
+
+
+	for(i = 3; i < 13; i++) {
+		printk("big_test: spawning thread %d.\n", i);
+		kernel_thread(sv_test_2_w, sv, 0);
+		down(&talkback);
+	}
+
+	printk("big_test: spawning wake-up thread.\n");
+	kernel_thread(sv_test_2_s, sv, 0);
+
+	down(&talkback);
+}
+
+sv_t int_test_sv;
+spinlock_t int_test_spin = SPIN_LOCK_UNLOCKED;
+int int_test_ready;
+static int irqtestcount;
+
+static int interrupt_test_worker(void *unused) 
+{
+	int id = ++irqtestcount;
+	int it = 0;
+			unsigned long flags, flags2;
+
+	printk("ITW: thread %d started.\n", id);
+
+	while(1) {
+		__save_flags(flags2);
+		if(jiffies % 3) {
+			printk("ITW %2d %5d: irqsaving          (%lx)\n", id, it, flags2);
+			spin_lock_irqsave(&int_test_spin, flags);
+		} else {
+			printk("ITW %2d %5d: spin_lock_irqing   (%lx)\n", id, it, flags2);
+			spin_lock_irq(&int_test_spin);
+		}
+
+		__save_flags(flags2);
+		printk("ITW %2d %5d: locked, sv_waiting (%lx).\n", id, it, flags2);
+		sv_wait(&int_test_sv, 0, 0);
+
+		__save_flags(flags2);
+		printk("ITW %2d %5d: wait finished      (%lx), pausing\n", id, it, flags2);
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(jiffies & 0xf);
+		if(current->state != TASK_RUNNING)
+		  printk("ITW:  current->state isn't RUNNING after schedule!\n");
+		it++;
+	}
+}
+
+static void interrupt_test(void) 
+{
+	int i;
+
+	printk("interrupt_test: initing sv.\n");
+	sv_init(&int_test_sv, &int_test_spin, SV_MON_SPIN | SV_INTS);
+
+	for(i = 0; i < SV_INTERRUPT_TEST_WORKERS; i++) {
+		printk("interrupt_test: starting test thread %d.\n", i);
+		kernel_thread(interrupt_test_worker, 0, 0);
+	}
+	printk("interrupt_test: done with init part.\n");
+	int_test_ready = 1;
+}
+
+int sv_test(void) 
+{
+	spinlock_t s = SPIN_LOCK_UNLOCKED;
+
+	sv_init(&sv, &s, SV_MON_SPIN);
+	printk("sv_test: starting sv_test_1_w.\n");
+	kernel_thread(sv_test_1_w, &s, 0);
+	printk("sv_test: starting sv_test_1_s.\n");
+	kernel_thread(sv_test_1_s, &s, 0);
+
+	printk("sv_test: waiting for talkback.\n");
+	down(&talkback); down(&talkback);
+	printk("sv_test: talkback happened, sv_destroying.\n");
+	sv_destroy(&sv);
+
+	count = 0;
+
+	printk("sv_test: beginning big_test on sv.\n");
+
+	sv_init(&sv, &monitor, SV_MON_SEMA);
+	big_test(&sv);
+	sv_destroy(&sv);
+
+	printk("sv_test: beginning big_test on sv_filo.\n");
+	sv_init(&sv_filo, &monitor, SV_MON_SEMA | SV_ORDER_FILO);
+	big_test(&sv_filo);
+	sv_destroy(&sv_filo);
+
+	interrupt_test();
+
+	printk("sv_test: done.\n");
+	return 0;
+}
+
+__initcall(sv_test);
+
+#endif /* RUN_SV_TEST */
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/sn1/synergy.c linux/arch/ia64/sn/sn1/synergy.c
--- v2.4.3/linux/arch/ia64/sn/sn1/synergy.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/sn1/synergy.c	Thu Apr  5 12:51:47 2001
@@ -8,9 +8,12 @@
 
 
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/proc_fs.h>
 
 #include <asm/ptrace.h>
 #include <linux/devfs_fs_kernel.h>
@@ -26,8 +29,6 @@
 void setclear_mask_a(int irq, int cpuid, int set);
 void * kmalloc(size_t size, int flags);
 
-extern struct sn1_cnode_action_list *sn1_node_actions[];
-
 
 void
 synergy_intr_alloc(int bit, int cpuid) {
@@ -40,9 +41,7 @@
 {
 	int irq;
 	unsigned is_b;
-int nasid;
 
-nasid = cpuid_to_nasid(cpuid);
 	irq = bit_pos_to_irq(bit);
 
 	is_b = (cpuid_to_slice(cpuid)) & 1;
@@ -202,3 +201,229 @@
 		REMOTE_SYNERGY_STORE(nasid, synergy, reg, val);
 	}
 }
+
+#if defined(CONFIG_IA64_SGI_SYNERGY_PERF)
+
+/*
+ * Synergy perf registers. Multiplexed via timer_interrupt
+ */
+static struct proc_dir_entry *synergy_perf_proc = NULL;
+
+/*
+ * read handler for /proc/synergy
+ */
+static int
+synergy_perf_read_proc (char *page, char **start, off_t off,
+                                 int count, int *eof, void *data)
+{
+	cnodeid_t       cnode;
+	nodepda_t       *npdap;
+	synergy_perf_t	*p;
+	int		len = 0;
+
+	len += sprintf(page+len, "# cnode module slot event synergy-A synergy-B\n");
+
+	/* walk the event list for each node */
+	for (cnode=0; cnode < numnodes; cnode++) {
+		npdap = NODEPDA(cnode);
+		if (npdap->synergy_perf_enabled == 0) {
+			len += sprintf(page+len, "# DISABLED\n");
+			break;
+		}
+
+		spin_lock_irq(&npdap->synergy_perf_lock);
+		for (p = npdap->synergy_perf_first; p;) {
+			uint64_t cnt_a=0, cnt_b=0;
+
+			if (p->intervals > 0) {
+				cnt_a = p->counts[0] * npdap->synergy_active_intervals / p->intervals;
+				cnt_b = p->counts[1] * npdap->synergy_active_intervals / p->intervals;
+			}
+
+			len += sprintf(page+len, "%d %d %d %12lx %lu %lu\n",
+				(int)cnode, (int)npdap->module_id, (int)npdap->slotdesc,
+				p->modesel, cnt_a, cnt_b);
+
+			p = p->next;
+			if (p == npdap->synergy_perf_first)
+				break;
+		}
+		spin_unlock_irq(&npdap->synergy_perf_lock);
+	}
+
+	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
+synergy_perf_append(uint64_t modesel)
+{
+	int		cnode;
+	nodepda_t       *npdap;
+	synergy_perf_t	*p;
+	int		err = 0;
+
+	/* bit 45 is enable */
+	modesel |= (1UL << 45);
+
+	for (cnode=0; cnode < numnodes; cnode++) {
+		/* for each node, insert a new synergy_perf entry */
+		if ((npdap = NODEPDA(cnode)) == NULL) {
+			printk("synergy_perf_append: cnode=%d NODEPDA(cnode)==NULL, nodepda=%p\n", cnode, nodepda);
+			continue;
+		}
+
+		/* XX use kmem_alloc_node() when it is implemented */
+		p = (synergy_perf_t *)kmalloc(sizeof(synergy_perf_t), GFP_KERNEL);
+		if (p == NULL)
+			err = -ENOMEM;
+		else {
+			memset(p, 0, sizeof(synergy_perf_t));
+			p->modesel = modesel;
+			if (npdap->synergy_perf_data == NULL) {
+				/* circular list */
+				p->next = p;
+				npdap->synergy_perf_data = p;
+				npdap->synergy_perf_first = p;
+			}
+			else {
+				/*
+				 * Jumble up the insertion order so we get better sampling.
+				 * Once the list is complete, "first" stays the same so the
+				 * reporting order is consistent.
+				 */
+				p->next = npdap->synergy_perf_first->next;
+				npdap->synergy_perf_first->next = p;
+				npdap->synergy_perf_first = p->next;
+			}
+		}
+	}
+
+	return err;
+}
+
+static int
+synergy_perf_write_proc (struct file *file, const char *buffer,
+                                unsigned long count, void *data)
+{
+	int		cnode;
+	nodepda_t       *npdap;
+	uint64_t	modesel;
+	char		cmd[64];
+	extern long	atoi(char *);
+    
+	if (count == sizeof(uint64_t)) {
+	    if (copy_from_user(&modesel, buffer, sizeof(uint64_t)))
+		    return -EFAULT;
+	    synergy_perf_append(modesel);
+	}
+	else {
+	    if (copy_from_user(cmd, buffer, count < sizeof(cmd) ? count : sizeof(cmd)))
+		    return -EFAULT;
+	    if (strncmp(cmd, "enable", 6) == 0) {
+		/* enable counting */
+		for (cnode=0; cnode < numnodes; cnode++) {
+			npdap = NODEPDA(cnode);
+			npdap->synergy_perf_enabled = 1;
+		}
+		printk("NOTICE: synergy perf counting enabled\n");
+	    }
+	    else
+	    if (strncmp(cmd, "disable", 7) == 0) {
+		/* disable counting */
+		for (cnode=0; cnode < numnodes; cnode++) {
+			npdap = NODEPDA(cnode);
+			npdap->synergy_perf_enabled = 0;
+		}
+		printk("NOTICE: synergy perf counting disabled\n");
+	    }
+	    else
+	    if (strncmp(cmd, "frequency", 9) == 0) {
+		/* set the update frequency (timer-interrupts per update) */
+		int freq;
+
+		if (count < 12)
+			return -EINVAL;
+		freq = atoi(cmd + 10);
+		if (freq <= 0 || freq > 100)
+			return -EINVAL;
+		for (cnode=0; cnode < numnodes; cnode++) {
+			npdap = NODEPDA(cnode);
+			npdap->synergy_perf_freq = (uint64_t)freq;
+		}
+		printk("NOTICE: synergy perf freq set to %d\n", freq);
+	    }
+	    else
+		return -EINVAL;
+	}
+	
+	return count;
+}
+
+void
+synergy_perf_update(int cpu)
+{
+	nasid_t		nasid;
+	cnodeid_t       cnode = cpuid_to_cnodeid(cpu);
+	struct nodepda_s *npdap;
+	extern struct nodepda_s *nodepda;
+
+	if (nodepda == NULL || (npdap=NODEPDA(cnode)) == NULL || npdap->synergy_perf_enabled == 0 ||
+		npdap->synergy_perf_data == NULL) {
+		/* I/O not initialized, or not enabled, or no events to monitor */
+		return;
+	}
+
+	if (npdap->synergy_inactive_intervals++ % npdap->synergy_perf_freq != 0) {
+		/* don't multiplex on every timer interrupt */
+		return;
+	}
+
+	/*
+	 * Read registers for last interval and increment counters.
+	 * Hold the per-node synergy_perf_lock so concurrent readers get
+	 * consistent values.
+	 */
+	spin_lock_irq(&npdap->synergy_perf_lock);
+
+	nasid = cpuid_to_nasid(cpu);
+	npdap->synergy_active_intervals++;
+	npdap->synergy_perf_data->intervals++;
+
+	npdap->synergy_perf_data->counts[0] += 0xffffffffffUL &
+		REMOTE_SYNERGY_LOAD(nasid, 0, PERF_CNTR0_A);
+
+	npdap->synergy_perf_data->counts[1] += 0xffffffffffUL &
+		REMOTE_SYNERGY_LOAD(nasid, 1, PERF_CNTR0_B);
+
+	/* skip to next in circular list */
+	npdap->synergy_perf_data = npdap->synergy_perf_data->next;
+
+	spin_unlock_irq(&npdap->synergy_perf_lock);
+
+	/* set the counter 0 selection modes for both A and B */
+	REMOTE_SYNERGY_STORE(nasid, 0, PERF_CNTL0_A, npdap->synergy_perf_data->modesel);
+	REMOTE_SYNERGY_STORE(nasid, 1, PERF_CNTL0_B, npdap->synergy_perf_data->modesel);
+
+	/* and reset the counter registers to zero */
+	REMOTE_SYNERGY_STORE(nasid, 0, PERF_CNTR0_A, 0UL);
+	REMOTE_SYNERGY_STORE(nasid, 1, PERF_CNTR0_B, 0UL);
+}
+
+void
+synergy_perf_init(void)
+{
+        if ((synergy_perf_proc = create_proc_entry("synergy", 0644, NULL)) != NULL) {
+                synergy_perf_proc->read_proc = synergy_perf_read_proc;
+                synergy_perf_proc->write_proc = synergy_perf_write_proc;
+                printk("markgw: synergy_perf_init()\n");
+        }
+}
+
+#endif /* CONFIG_IA64_SGI_SYNERGY_PERF */
+
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/tools/print_offsets.awk linux/arch/ia64/tools/print_offsets.awk
--- v2.4.3/linux/arch/ia64/tools/print_offsets.awk	Fri Jul 14 16:08:12 2000
+++ linux/arch/ia64/tools/print_offsets.awk	Thu Apr  5 12:51:47 2001
@@ -28,6 +28,10 @@
 	inside_table = 0
 }
 
+/.*[.]rodata/ {
+	inside_table = 0
+}
+
 {
 	if (inside_table) {
 		if ($1 == "//") getline;
@@ -61,7 +65,7 @@
 	inside_table = 1
 }
 
-/tab#:/ {
+/tab\#:/ {
 	inside_table = 1
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/tools/print_offsets.c linux/arch/ia64/tools/print_offsets.c
--- v2.4.3/linux/arch/ia64/tools/print_offsets.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/tools/print_offsets.c	Thu Apr  5 12:51:47 2001
@@ -1,8 +1,8 @@
 /*
  * Utility to generate asm-ia64/offsets.h.
  *
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Note that this file has dual use: when building the kernel
  * natively, the file is translated into a binary and executed.  When
@@ -45,9 +45,8 @@
     { "IA64_PT_REGS_SIZE",		sizeof (struct pt_regs) },
     { "IA64_SWITCH_STACK_SIZE",		sizeof (struct switch_stack) },
     { "IA64_SIGINFO_SIZE",		sizeof (struct siginfo) },
-#ifdef CONFIG_IA64_NEW_UNWIND
+    { "IA64_CPU_SIZE",			sizeof (struct cpuinfo_ia64) },
     { "UNW_FRAME_INFO_SIZE",		sizeof (struct unw_frame_info) },
-#endif
     { "", 0 },			/* spacer */
     { "IA64_TASK_PTRACE_OFFSET",	offsetof (struct task_struct, ptrace) },
     { "IA64_TASK_SIGPENDING_OFFSET",	offsetof (struct task_struct, sigpending) },
@@ -58,6 +57,9 @@
 #ifdef CONFIG_IA32_SUPPORT
     { "IA64_TASK_THREAD_SIGMASK_OFFSET",offsetof (struct task_struct, thread.un.sigmask) },
 #endif
+#ifdef CONFIG_PERFMON
+    { "IA64_TASK_PFM_NOTIFY_OFFSET",	offsetof(struct task_struct, thread.pfm_pend_notify) },
+#endif
     { "IA64_TASK_PID_OFFSET",		offsetof (struct task_struct, pid) },
     { "IA64_TASK_MM_OFFSET",		offsetof (struct task_struct, mm) },
     { "IA64_PT_REGS_CR_IPSR_OFFSET",	offsetof (struct pt_regs, cr_ipsr) },
@@ -157,6 +159,11 @@
     { "IA64_SIGCONTEXT_FR6_OFFSET",	offsetof (struct sigcontext, sc_fr[6]) },
     { "IA64_CLONE_VFORK",		CLONE_VFORK },
     { "IA64_CLONE_VM",			CLONE_VM },
+    { "IA64_CPU_IRQ_COUNT_OFFSET",	offsetof (struct cpuinfo_ia64, irq_stat.f.irq_count) },
+    { "IA64_CPU_BH_COUNT_OFFSET",	offsetof (struct cpuinfo_ia64, irq_stat.f.bh_count) },
+    { "IA64_CPU_SOFTIRQ_ACTIVE_OFFSET",		offsetof (struct cpuinfo_ia64, softirq.active) },
+    { "IA64_CPU_SOFTIRQ_MASK_OFFSET",		offsetof (struct cpuinfo_ia64, softirq.mask) },
+    { "IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET",	offsetof (struct cpuinfo_ia64, phys_stacked_size_p8) },
 };
 
 static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/vmlinux.lds.S linux/arch/ia64/vmlinux.lds.S
--- v2.4.3/linux/arch/ia64/vmlinux.lds.S	Fri Aug 11 19:09:06 2000
+++ linux/arch/ia64/vmlinux.lds.S	Thu Apr  5 12:51:47 2001
@@ -5,10 +5,18 @@
 
 OUTPUT_FORMAT("elf64-ia64-little")
 OUTPUT_ARCH(ia64)
-ENTRY(_start)
+ENTRY(phys_start)
 SECTIONS
 {
+  /* Sections to be discarded */
+  /DISCARD/ : {
+	*(.text.exit)
+	*(.data.exit)
+	*(.exitcall.exit)
+	}
+
   v = PAGE_OFFSET;	/* this symbol is here to make debugging easier... */
+  phys_start = _start - PAGE_OFFSET;
 
   . = KERNEL_START;
 
@@ -16,11 +24,11 @@
   _stext = .;
   .text : AT(ADDR(.text) - PAGE_OFFSET)
     {
-	*(__ivt_section)
+	*(.text.ivt)
 	/* these are not really text pages, but the zero page needs to be in a fixed location: */
 	*(__special_page_section)
 	__start_gate_section = .;
-	*(__gate_section)
+	*(.text.gate)
 	__stop_gate_section = .;
 	*(.text)
     }
@@ -34,7 +42,7 @@
 
   /* Read-only data */
 
-  __gp = ALIGN(8) + 0x200000;
+  __gp = ALIGN(16) + 0x200000;	/* gp must be 16-byte aligned for exc. table */
 
   /* Global data */
   _data = .;
@@ -60,13 +68,19 @@
 	{ *(__ksymtab) }
   __stop___ksymtab = .;
 
-  /* Unwind table */
+  __start___kallsyms = .;	/* All kernel symbols for debugging */
+  __kallsyms : AT(ADDR(__kallsyms) - PAGE_OFFSET)
+	{ *(__kallsyms) }
+  __stop___kallsyms = .;
+
+  /* Unwind info & table: */
+  .IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - PAGE_OFFSET)
+	{ *(.IA_64.unwind_info*) }
+  . = ALIGN(8);
   ia64_unw_start = .;
   .IA_64.unwind : AT(ADDR(.IA_64.unwind) - PAGE_OFFSET)
-	{ *(.IA_64.unwind) }
+	{ *(.IA_64.unwind*) }
   ia64_unw_end = .;
-  .IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - PAGE_OFFSET)
-	{ *(.IA_64.unwind_info) }
 
   .rodata : AT(ADDR(.rodata) - PAGE_OFFSET)
 	{ *(.rodata) }
@@ -129,13 +143,6 @@
 	{ *(.bss) *(COMMON) }
   . = ALIGN(64 / 8);
   _end = .;
-
-  /* Sections to be discarded */
-  /DISCARD/ : {
-	*(.text.exit)
-	*(.data.exit)
-	*(.exitcall.exit)
-	}
 
   /* Stabs debugging sections.  */
   .stab 0 : { *(.stab) }
diff -u --recursive --new-file v2.4.3/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- v2.4.3/linux/arch/m68k/amiga/config.c	Thu Jan  4 13:00:55 2001
+++ linux/arch/m68k/amiga/config.c	Fri Apr 13 20:26:07 2001
@@ -769,20 +769,6 @@
     return 0;
 }
 
-void dbprintf(const char *fmt , ...)
-{
-	static char buf[1024];
-	va_list args;
-	extern void console_print (const char *str);
-	extern int vsprintf(char * buf, const char * fmt, va_list args);
-
-	va_start(args, fmt);
-	vsprintf(buf, fmt, args);
-	va_end(args);
-
-	console_print (buf);
-}
-
 static NORET_TYPE void amiga_reset( void )
     ATTRIB_NORET;
 
diff -u --recursive --new-file v2.4.3/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.4.3/linux/arch/m68k/config.in	Thu Jan  4 13:00:55 2001
+++ linux/arch/m68k/config.in	Tue Apr 17 17:19:25 2001
@@ -4,6 +4,8 @@
 #
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Linux/68k Kernel Configuration"
 
@@ -487,8 +489,10 @@
    fi
 fi
 if [ "$CONFIG_APOLLO" = "y" ]; then
-   bool 'Support for DN serial port (dummy)' CONFIG_SERIAL
+   bool 'Support for DN serial port (dummy)' CONFIG_DN_SERIAL
    bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
+
+   define_tristate CONFIG_SERIAL $CONFIG_DN_SERIAL
 fi 
 bool 'Support for user serial device modules' CONFIG_USERIAL
 bool 'Watchdog Timer Support'	CONFIG_WATCHDOG
diff -u --recursive --new-file v2.4.3/linux/arch/m68k/ifpsp060/src/fpsp.S linux/arch/m68k/ifpsp060/src/fpsp.S
--- v2.4.3/linux/arch/m68k/ifpsp060/src/fpsp.S	Tue Mar  6 19:44:35 2001
+++ linux/arch/m68k/ifpsp060/src/fpsp.S	Fri Apr  6 10:42:47 2001
@@ -19594,7 +19594,7 @@
 # in the data register file. If it's actually out in memory, use one of	#
 # the mem_read() routines to fetch it. If the mem_read() access returns	#
 # a failing value, exit through the special facc_in() routine which	#
-# will create an acess error exception frame from the current exception #
+# will create an access error exception frame from the current exception #
 # frame.								#
 # 	Immediate data and regular data accesses are separated because 	#
 # if an immediate data access fails, the resulting fault status		#
@@ -24608,7 +24608,7 @@
 # made out of the current exception stack frame. 			#
 #	So, we first call restore() which makes sure that any updated	#
 # -(an)+ register gets returned to its pre-exception value and then	#
-# we change the stack to an acess error stack frame.			#
+# we change the stack to an access error stack frame.			#
 #									#
 #########################################################################
 
diff -u --recursive --new-file v2.4.3/linux/arch/m68k/ifpsp060/src/pfpsp.S linux/arch/m68k/ifpsp060/src/pfpsp.S
--- v2.4.3/linux/arch/m68k/ifpsp060/src/pfpsp.S	Tue Mar  6 19:44:36 2001
+++ linux/arch/m68k/ifpsp060/src/pfpsp.S	Fri Apr  6 10:42:48 2001
@@ -14568,7 +14568,7 @@
 # made out of the current exception stack frame. 			#
 #	So, we first call restore() which makes sure that any updated	#
 # -(an)+ register gets returned to its pre-exception value and then	#
-# we change the stack to an acess error stack frame.			#
+# we change the stack to an access error stack frame.			#
 #									#
 #########################################################################
 
diff -u --recursive --new-file v2.4.3/linux/arch/m68k/kernel/semaphore.c linux/arch/m68k/kernel/semaphore.c
--- v2.4.3/linux/arch/m68k/kernel/semaphore.c	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/kernel/semaphore.c	Tue Apr 17 17:19:25 2001
@@ -130,111 +130,3 @@
 {
 	return waking_non_zero_trylock(sem);
 }
-
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	__up_read(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-                if (!sem->read_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	__up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);	/* put ourselves at the end of the list */
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	current->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (atomic_read(&sem->count) >= 0)
-		wake_up(&sem->wait);
-}
-
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-void rwsem_wake_readers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->read_bias_granted, 1))
-		BUG();
-	wake_up(&sem->wait);
-}
-
-void rwsem_wake_writer(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->write_bias_granted, 1))
-		BUG();
-	wake_up(&sem->write_bias_wait);
-}
diff -u --recursive --new-file v2.4.3/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c
--- v2.4.3/linux/arch/m68k/kernel/setup.c	Thu Jan  4 13:00:55 2001
+++ linux/arch/m68k/kernel/setup.c	Fri Apr 13 20:26:07 2001
@@ -39,10 +39,6 @@
 #include <linux/blk.h>
 #endif
 
-#ifndef CONFIG_AMIGA
-#define dbprintf	printk
-#endif
-
 unsigned long m68k_machtype;
 unsigned long m68k_cputype;
 unsigned long m68k_fputype;
diff -u --recursive --new-file v2.4.3/linux/arch/m68k/mm/motorola.c linux/arch/m68k/mm/motorola.c
--- v2.4.3/linux/arch/m68k/mm/motorola.c	Mon Aug  7 21:02:27 2000
+++ linux/arch/m68k/mm/motorola.c	Fri Apr  6 10:42:48 2001
@@ -286,6 +286,7 @@
 }
 
 extern char __init_begin, __init_end;
+extern unsigned long totalram_pages;
 
 void free_initmem(void)
 {
@@ -296,6 +297,7 @@
 		virt_to_page(addr)->flags &= ~(1 << PG_reserved);
 		set_page_count(virt_to_page(addr), 1);
 		free_page(addr);
+		totalram_pages++;
 	}
 }
 
diff -u --recursive --new-file v2.4.3/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c
--- v2.4.3/linux/arch/m68k/q40/config.c	Tue Mar  6 19:44:36 2001
+++ linux/arch/m68k/q40/config.c	Fri Apr  6 10:42:48 2001
@@ -238,7 +238,7 @@
     mach_max_dma_address = 32*1024*1024;   /* no DMA at all, but ide-scsi requires it.. */
 
 
-/* userfull 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 ))
       {
diff -u --recursive --new-file v2.4.3/linux/arch/mips/Makefile linux/arch/mips/Makefile
--- v2.4.3/linux/arch/mips/Makefile	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/Makefile	Fri Apr 13 20:26:07 2001
@@ -17,8 +17,10 @@
 #
 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
@@ -26,16 +28,16 @@
 endif
 
 #
-# The ELF GCC uses -G0 -mabicalls -fpic as default.  We don't need PIC
-# code in the kernel since it only slows down the whole thing.  For the
-# old GCC these options are just the defaults.  At some point we might
-# make use of global pointer optimizations.
+# GCC uses -G0 -mabicalls -fpic as default.  We don't want PIC in the kernel
+# code since it only slows down the whole thing.  At some point we might make
+# use of global pointer optimizations but their use of $28 conflicts with
+# the current pointer optimization.
 #
 # The DECStation requires an ECOFF kernel for remote booting, other MIPS
 # machines may also.  Since BFD is incredibly buggy with respect to
 # crossformat linking we rely on the elf2ecoff tool for format conversion.
 #
-CFLAGS		+= -G 0 -mno-abicalls -fno-pic
+GCCFLAGS	:= -G 0 -mno-abicalls -fno-pic
 LINKFLAGS	+= -static -G 0
 MODFLAGS	+= -mlong-calls
 
@@ -47,37 +49,63 @@
 # CPU-dependent compiler/assembler options for optimization.
 #
 ifdef CONFIG_CPU_R3000
-CFLAGS		:= $(CFLAGS) -mcpu=r3000 -mips1
+GCCFLAGS	+= -mcpu=r3000 -mips1
+endif
+ifdef CONFIG_CPU_R3912
+GCCFLAGS	+= -mcpu=r3000 -mips1
 endif
 ifdef CONFIG_CPU_R6000
-CFLAGS		:= $(CFLAGS) -mcpu=r6000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r6000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R4300
-CFLAGS		:= $(CFLAGS) -mcpu=r4300 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r4300 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R4X00
-CFLAGS		:= $(CFLAGS) -mcpu=r4600 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
+endif
+ifdef CONFIG_CPU_MIPS32
+GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R5000
-CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
+endif
+ifdef CONFIG_CPU_R5432
+GCCFLAGS        += -mcpu=r8000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_NEVADA
-CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap -mmad
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap -mmad
+endif
+ifdef CONFIG_CPU_RM7000
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R8000
-CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R10000
-CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
 endif
 
+ifdef CONFIG_MIPS_FPU_EMULATOR
+CORE_FILES	+=arch/mips/math-emu/fpu_emulator.o
+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)
+
 #
 # Board-dependent options and extra files
 #
 ifdef CONFIG_ALGOR_P4032
 CORE_FILES    += arch/mips/algor/algor.o
 SUBDIRS       += arch/mips/algor
-#LOADADDR      += 0x80000000
+LOADADDR      += 0x80000000
 endif
 
 #
@@ -90,6 +118,18 @@
 LOADADDR      += 0x80040000
 endif
 
+ifdef CONFIG_MIPS_ATLAS
+LIBS          += arch/mips/mips-boards/atlas/atlas.o arch/mips/mips-boards/generic/mipsboards.o
+SUBDIRS       += arch/mips/mips-boards/generic arch/mips/mips-boards/atlas
+LOADADDR      += 0x80100000
+endif
+
+ifdef CONFIG_MIPS_MALTA
+LIBS          += arch/mips/mips-boards/malta/malta.o arch/mips/mips-boards/generic/mipsboards.o
+SUBDIRS       += arch/mips/mips-boards/malta arch/mips/mips-boards/generic
+LOADADDR      += 0x80100000
+endif
+
 #
 # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
 #
@@ -100,12 +140,6 @@
 LOADADDR      += 0x80080000
 endif
 
-ifdef CONFIG_COBALT_MICRO_SERVER
-ARCHIVES      += arch/mips/cobalt/cobalt.o
-SUBDIRS       += arch/mips/cobalt
-LOADADDR      += 0x80000000
-endif
-
 ifdef CONFIG_SNI_RM200_PCI
 CORE_FILES    += arch/mips/sni/sni.o
 SUBDIRS       += arch/mips/sni arch/mips/arc
@@ -114,7 +148,8 @@
 endif
 
 ifdef CONFIG_SGI_IP22
-LIBS          += arch/mips/sgi/kernel/sgikern.a arch/mips/arc/arclib.a
+CORE_FILES    += arch/mips/sgi/kernel/ip22-kern.o
+LIBS          += arch/mips/arc/arclib.a
 SUBDIRS       += arch/mips/sgi/kernel arch/mips/arc
 #
 # Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
@@ -152,28 +187,74 @@
 endif
 
 #
-# Choosing incompatible machines durings configuration will result in
-# error messages during linking.  Select a default linkscript if
-# none has been choosen above.
 #
-ifndef LINKSCRIPT
-ifndef CONFIG_CPU_LITTLE_ENDIAN
-LINKSCRIPT    = arch/mips/ld.script.big
-else
-LINKSCRIPT    = arch/mips/ld.script.little
+# NEC DDB Vrc-5476
+#
+ifdef CONFIG_DDB5476
+SUBDIRS       += arch/mips/ddb5476
+LIBS          += arch/mips/ddb5476/ddb5476.a
+LOADADDR      += 0x80080000
 endif
+
+#
+# Galileo EV64120 Board
+#
+ifdef CONFIG_MIPS_EV64120
+LIBS          += arch/mips/galileo-boards/ev64120/ev64120.o
+SUBDIRS       += arch/mips/galileo-boards/ev64120
+LOADADDR      += 0x80100000
 endif
-LINKFLAGS     += -T $(word 1,$(LINKSCRIPT))
 
-ifdef LOADADDR
-LINKFLAGS     += -Ttext $(word 1,$(LOADADDR))
+#
+# Galileo EV96100 Board
+#
+ifdef CONFIG_MIPS_EV96100
+LIBS          += arch/mips/galileo-boards/ev96100/ev96100.o arch/mips/galileo-boards/generic/galboards.o
+SUBDIRS       += arch/mips/galileo-boards/generic arch/mips/galileo-boards/ev96100
+LOADADDR      += 0x80100000
 endif
 
 #
-# The pipe options is bad for my low-mem machine
-# Uncomment this if you want this.
+# Momentum Ocelot board
+#
+ifdef CONFIG_MOMENCO_OCELOT
+LIBS          += 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
+
 #
-CFLAGS		+= -pipe
+# 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
+LOADADDR      += 0x80000000
+endif
+
+#
+# ITE 8172 eval board with QED 5231 CPU
+#
+ifdef CONFIG_MIPS_ITE8172
+LIBS		+= arch/mips/ite-boards/qed-4n-s01b/ite.o		     \
+		   arch/mips/ite-boards/generic/it8172.o
+SUBDIRS		+= arch/mips/ite-boards/generic				     \
+		   arch/mips/ite-boards/qed-4n-s01b
+LOADADDR	+= 0x80100000
+endif
+
+#
+# Choosing incompatible machines durings configuration will result in
+# error messages during linking.  Select a default linkscript if
+# none has been choosen above.
+#
+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)/' <$< >$@
+LINKFLAGS	+= -T arch/$(ARCH)/ld.script
 
 HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
 
@@ -197,8 +278,18 @@
 	$(ORIONBOOT) orionboot
 endif
 
+ifdef CONFIG_MIPS_EV64120
+GALILEOBOOT = $(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120
+
+gboot: vmlinux
+	$(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120/compressed 
+endif
+
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
+vmlinux.ecoff: vmlinux
+	@$(MAKEBOOT) $@
+
 zImage: vmlinux
 	@$(MAKEBOOT) zImage
 
@@ -209,7 +300,7 @@
 
 archclean:
 	@$(MAKEBOOT) clean
-	$(MAKE) -C arch/$(ARCH)/kernel clean
+	rm -f arch/$(ARCH)/ld.script
 	$(MAKE) -C arch/$(ARCH)/tools clean
 	$(MAKE) -C arch/mips/baget clean
 
diff -u --recursive --new-file v2.4.3/linux/arch/mips/arc/Makefile linux/arch/mips/arc/Makefile
--- v2.4.3/linux/arch/mips/arc/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/Makefile	Fri Apr 13 20:26:07 2001
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
 #
 # Makefile for the SGI arcs prom monitor library routines
 # under Linux.
@@ -10,7 +9,10 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 L_TARGET = arclib.a
-L_OBJS  = console.o init.o printf.o memory.o tree.o env.o cmdline.o misc.o \
-	  time.o file.o identify.o
+
+obj-y		+= console.o init.o memory.o tree.o env.o cmdline.o misc.o \
+		   time.o file.o identify.o
+
+obj-$(CONFIG_ARC_CONSOLE)   += arc_con.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/mips/arc/arc_con.c linux/arch/mips/arc/arc_con.c
--- v2.4.3/linux/arch/mips/arc/arc_con.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/arc/arc_con.c	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,69 @@
+/*
+ * Wrap-around code for a console using the
+ * ARC io-routines.
+ *
+ * Copyright (c) 1998 Harald Koerfgen 
+ */
+
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+
+extern char prom_getchar (void);
+extern void prom_printf (char *, ...);
+
+static void prom_console_write(struct console *co, const char *s,
+			       unsigned count)
+{
+	unsigned i;
+
+	/*
+	 *    Now, do each character
+	 */
+	for (i = 0; i < count; i++) {
+		if (*s == 10)
+			prom_printf("%c", 13);
+		prom_printf("%c", *s++);
+	}
+}
+
+static int prom_console_wait_key(struct console *co)
+{
+	return prom_getchar();
+}
+
+static int __init prom_console_setup(struct console *co, char *options)
+{
+	return 0;
+}
+
+static kdev_t prom_console_device(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static struct console arc_cons = {
+	"ttyS",
+	prom_console_write,
+	NULL,
+	prom_console_device,
+	prom_console_wait_key,
+	NULL,
+	prom_console_setup,
+	CON_PRINTBUFFER,
+	-1,
+	0,
+	NULL
+};
+
+/*
+ *    Register console.
+ */
+
+void __init arc_console_init(void)
+{
+	register_console(&arc_cons);
+}
diff -u --recursive --new-file v2.4.3/linux/arch/mips/arc/cmdline.c linux/arch/mips/arc/cmdline.c
--- v2.4.3/linux/arch/mips/arc/cmdline.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/cmdline.c	Fri Apr 13 20:26:07 2001
@@ -2,8 +2,6 @@
  * cmdline.c: Kernel command line creation using ARCS argc/argv.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: cmdline.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -12,9 +10,9 @@
 #include <asm/sgialib.h>
 #include <asm/bootinfo.h>
 
-/* #define DEBUG_CMDLINE */
+#undef DEBUG_CMDLINE
 
-char arcs_cmdline[CL_SIZE];
+char arcs_cmdline[COMMAND_LINE_SIZE];
 
 char * __init prom_getcmdline(void)
 {
diff -u --recursive --new-file v2.4.3/linux/arch/mips/arc/console.c linux/arch/mips/arc/console.c
--- v2.4.3/linux/arch/mips/arc/console.c	Mon Feb 28 07:18:20 2000
+++ linux/arch/mips/arc/console.c	Fri Apr 13 20:26:07 2001
@@ -1,50 +1,99 @@
 /*
- * console.c: SGI arcs console code.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  *
  * Copyright (C) 1996 David S. Miller (dm@sgi.com)
  * Compability with board caches, Ulf Carlsson
- *
- * $Id: console.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
  */
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <asm/sgialib.h>
 #include <asm/bcache.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+
+#ifdef CONFIG_ARC_CONSOLE
+#define __init
+#endif
 
-/* The romvec is not compatible with board caches.  Thus we disable it during
- * romvec action.  Since r4xx0.c is always compiled and linked with your kernel,
- * this shouldn't cause any harm regardless what MIPS processor you have.
+/*
+ * 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
+ * kernel, this shouldn't cause any harm regardless what MIPS processor you
+ * have.
  *
- * The romvec write and read functions seem to interfere with the serial lines
+ * The ARC write and read functions seem to interfere with the serial lines
  * in some way. You should be careful with them.
  */
-extern struct bcache_ops *bcops;
 
-#ifdef CONFIG_SGI_PROM_CONSOLE
-void prom_putchar(char c)
-#else
 void __init prom_putchar(char c)
-#endif
 {
 	long cnt;
 	char it = c;
 
-	bcops->bc_disable();
+	bc_disable();
 	romvec->write(1, &it, 1, &cnt);
-	bcops->bc_enable();
+	bc_enable();
 }
 
-#ifdef CONFIG_SGI_PROM_CONSOLE
-char prom_getchar(void)
-#else
 char __init prom_getchar(void)
-#endif
 {
 	long cnt;
 	char c;
 
-	bcops->bc_disable();
+	bc_disable();
 	romvec->read(0, &c, 1, &cnt);
-	bcops->bc_enable();
+	bc_enable();
+
 	return c;
+}
+
+static char ppbuf[1024];
+
+void __init prom_printf(char *fmt, ...)
+{
+	va_list args;
+	char ch, *bptr;
+	int i;
+
+	va_start(args, fmt);
+	i = vsprintf(ppbuf, fmt, args);
+
+	bptr = ppbuf;
+
+	while ((ch = *(bptr++)) != 0) {
+		if (ch == '\n')
+			prom_putchar('\r');
+
+		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.3/linux/arch/mips/arc/identify.c linux/arch/mips/arc/identify.c
--- v2.4.3/linux/arch/mips/arc/identify.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/identify.c	Fri Apr 13 20:26:07 2001
@@ -6,8 +6,6 @@
  * This code is based on arch/mips/sgi/kernel/system.c, which is
  * 
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: identify.c,v 1.2 1999/02/25 21:04:13 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -19,50 +17,51 @@
 #include <asm/bootinfo.h>
 
 struct smatch {
-    char *name;
-    int group;
-    int type;
-    int flags;
+	char *name;
+	int group;
+	int type;
+	int flags;
 };
 
 static struct smatch mach_table[] = {
-    { "SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS },
-    { "Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0 },
-    { "PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0 },
-    { "RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0 }
+	{"SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS},
+	{"Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0},
+	{"PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0},
+	{"RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0}
 };
 
 int prom_flags;
 
-static struct smatch * __init string_to_mach(char *s)
+static struct smatch *__init string_to_mach(char *s)
 {
-    int i;
-    
-    for (i = 0; i < sizeof (mach_table); i++) {
-	if(!strcmp(s, mach_table[i].name))
-	    return &mach_table[i];
-    }
-    prom_printf("\nYeee, could not determine architecture type <%s>\n", s);
-    prom_printf("press a key to reboot\n");
-    prom_getchar();
-    romvec->imode();
-    return NULL;
+	int i;
+
+	for (i = 0; i < sizeof(mach_table); i++) {
+		if (!strcmp(s, mach_table[i].name))
+			return &mach_table[i];
+	}
+	prom_printf("\nYeee, could not determine architecture type <%s>\n",
+		    s);
+	prom_printf("press a key to reboot\n");
+	prom_getchar();
+	romvec->imode();
+	return NULL;
 }
 
 void __init prom_identify_arch(void)
 {
-    pcomponent *p;
-    struct smatch *mach;
-    
-    /* The root component tells us what machine architecture we
-     * have here.
-     */
-    p = prom_getchild(PROM_NULL_COMPONENT);
-    printk("ARCH: %s\n", p->iname);
-    mach = string_to_mach(p->iname);
-
-    mips_machgroup = mach->group;
-    mips_machtype = mach->type;
-    prom_flags = mach->flags;
-}
+	pcomponent *p;
+	struct smatch *mach;
 
+	/*
+	 * The root component tells us what machine architecture we
+	 * have here.
+	 */
+	p = prom_getchild(PROM_NULL_COMPONENT);
+	printk("ARCH: %s\n", p->iname);
+	mach = string_to_mach(p->iname);
+
+	mips_machgroup = mach->group;
+	mips_machtype = mach->type;
+	prom_flags = mach->flags;
+}
diff -u --recursive --new-file v2.4.3/linux/arch/mips/arc/init.c linux/arch/mips/arc/init.c
--- v2.4.3/linux/arch/mips/arc/init.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/init.c	Fri Apr 13 20:26:07 2001
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.5 2000/03/07 15:45:27 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.
@@ -23,7 +23,9 @@
 
 extern void prom_testtree(void);
 
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+extern void arc_setup_console(void);
+
+void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
 {
 	struct linux_promblock *pb;
 
@@ -33,7 +35,20 @@
 	prom_argv = argv;
 	prom_envp = envp;
 
-	if(pb->magic != 0x53435241) {
+#if 0
+	/* arc_printf should not use prom_printf as soon as we free
+	 * the prom buffers - This horribly breaks on Indys with framebuffer
+	 * as it simply stops after initialising swap - On the Indigo2 serial
+	 * console you will get A LOT illegal instructions - Only enable
+	 * this for early init crashes - This also brings up artefacts of
+	 * printing everything twice on serial console and on GFX Console
+	 * this has the effect of having the prom printing everything
+	 * in the small rectangle and the kernel printing around.
+	 */
+
+	arc_setup_console();
+#endif
+	if (pb->magic != 0x53435241) {
 		prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
 		while(1)
 			;
@@ -55,5 +70,4 @@
 		romvec->imode();
 	}
 #endif
-	return 0;
 }
diff -u --recursive --new-file v2.4.3/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c
--- v2.4.3/linux/arch/mips/arc/memory.c	Mon Aug  7 21:02:27 2000
+++ linux/arch/mips/arc/memory.c	Fri Apr 13 20:26:07 2001
@@ -3,8 +3,6 @@
  *           given to us from the ARCS firmware.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: memory.c,v 1.10 2000/01/27 23:21:57 ralf Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -47,31 +45,25 @@
 	"LoadedProgram",
 	"FirmwareTemporary",
 	"FirmwarePermanent",
-	"FreeContigiuous"
+	"FreeContiguous"
 };
 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
 #endif
 
-static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS];
-
-#define MEMTYPE_DONTUSE   0
-#define MEMTYPE_PROM      1
-#define MEMTYPE_FREE      2
-
 static inline int memtype_classify_arcs (union linux_memtypes type)
 {
 	switch (type.arcs) {
 	case arcs_fcontig:
 	case arcs_free:
-		return MEMTYPE_FREE;
+		return BOOT_MEM_RAM;
 	case arcs_atmp:
-		return MEMTYPE_PROM;
+		return BOOT_MEM_ROM_DATA;
 	case arcs_eblock:
 	case arcs_rvpage:
 	case arcs_bmem:
 	case arcs_prog:
 	case arcs_aperm:
-		return MEMTYPE_DONTUSE;
+		return BOOT_MEM_RESERVED;
 	default:
 		BUG();
 	}
@@ -83,15 +75,15 @@
 	switch (type.arc) {
 	case arc_free:
 	case arc_fcontig:
-		return MEMTYPE_FREE;
+		return BOOT_MEM_RAM;
 	case arc_atmp:
-		return MEMTYPE_PROM;
+		return BOOT_MEM_ROM_DATA;
 	case arc_eblock:
 	case arc_rvpage:
 	case arc_bmem:
 	case arc_prog:
 	case arc_aperm:
-		return MEMTYPE_DONTUSE;
+		return BOOT_MEM_RESERVED;
 	default:
 		BUG();
 	}
@@ -106,50 +98,13 @@
 	return memtype_classify_arc(type);
 }
 
-static inline unsigned long find_max_low_pfn(void)
-{
-	struct prom_pmemblock *p, *highest;
-	unsigned long pfn;
-
-	p = pblocks;
-	highest = 0;
-	while (p->size != 0) {
-		if (!highest || p->base > highest->base)
-			highest = p;
-		p++;
-	}
-
-	pfn = (highest->base + highest->size) >> PAGE_SHIFT;
-#ifdef DEBUG
-	prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn);
-#endif
-	return pfn;
-}
-
-static inline struct prom_pmemblock *find_largest_memblock(void)
-{
-	struct prom_pmemblock *p, *largest;
-
-	p = pblocks;
-	largest = 0;
-	while (p->size != 0) {
-		if (!largest || p->size > largest->size)
-			largest = p;
-		p++;
-	}
-
-	return largest;
-}
-
 void __init prom_meminit(void)
 {
-	struct prom_pmemblock *largest;
-	unsigned long bootmap_size;
 	struct linux_mdesc *p;
-	int totram;
-	int i = 0;
 
 #ifdef DEBUG
+	int i = 0;
+
 	prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
 	p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
 	while(p) {
@@ -160,77 +115,36 @@
 	}
 #endif
 
-	totram = 0;
-	i = 0;
 	p = PROM_NULL_MDESC;
 	while ((p = ArcGetMemoryDescriptor(p))) {
-		pblocks[i].type = prom_memtype_classify(p->type);
-		pblocks[i].base = p->base << PAGE_SHIFT;
-		pblocks[i].size = p->pages << PAGE_SHIFT;
-
-		switch (pblocks[i].type) {
-		case MEMTYPE_FREE:
-			totram += pblocks[i].size;
-#ifdef DEBUG
-			prom_printf("free_chunk[%d]: base=%08lx size=%x\n",
-				    i, pblocks[i].base,
-				    pblocks[i].size);
-#endif
-			i++;
-			break;
-		case MEMTYPE_PROM:
-#ifdef DEBUG
-			prom_printf("prom_chunk[%d]: base=%08lx size=%x\n",
-				    i, pblocks[i].base,
-				    pblocks[i].size);
-#endif
-			i++;
-			break;
-		default:
-			break;
-		}
-	}
-	pblocks[i].size = 0;
-
-	max_low_pfn = find_max_low_pfn();
-
-	largest = find_largest_memblock();
-	bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn);
+		unsigned long base, size;
+		long type;
 
-	for (i = 0; pblocks[i].size; i++)
-		if (pblocks[i].type == MEMTYPE_FREE)
-			free_bootmem(pblocks[i].base, pblocks[i].size);
+		base = p->base << PAGE_SHIFT;
+		size = p->pages << PAGE_SHIFT;
+		type = prom_memtype_classify(p->type);
 
-	/* This test is simpleminded.  It will fail if the bootmem bitmap
-	   falls into multiple adjacent ARC memory areas.  */
-	if (bootmap_size > largest->size) {
-		prom_printf("CRITIAL: overwriting PROM data.\n");
-		BUG();
+		add_memory_region(base, size, type);
 	}
-
-	/* Reserve the memory bootmap itself */
-	reserve_bootmem(largest->base, bootmap_size);
-
-	printk("PROMLIB: Total free ram %dK / %dMB.\n",
-	       totram >> 10, totram >> 20);
 }
 
 void __init
 prom_free_prom_memory (void)
 {
-	struct prom_pmemblock *p;
 	unsigned long freed = 0;
 	unsigned long addr;
+	int i;
 
-	for (p = pblocks; p->size != 0; p++) {
-		if (p->type != MEMTYPE_PROM)
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
 			continue;
 
-		addr = PAGE_OFFSET + p->base;
-		while (addr < p->base + p->size) {
-			ClearPageReserved(virt_to_page(addr));
-			set_page_count(virt_to_page(addr), 1);
-			free_page(addr);
+		addr = boot_mem_map.map[i].addr;
+		while (addr < boot_mem_map.map[i].addr
+			      + boot_mem_map.map[i].size) {
+			ClearPageReserved(virt_to_page(__va(addr)));
+			set_page_count(virt_to_page(__va(addr)), 1);
+			free_page((unsigned long)__va(addr));
 			addr += PAGE_SIZE;
 			freed += PAGE_SIZE;
 		}
diff -u --recursive --new-file v2.4.3/linux/arch/mips/arc/misc.c linux/arch/mips/arc/misc.c
--- v2.4.3/linux/arch/mips/arc/misc.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/misc.c	Fri Apr 13 20:26:07 2001
@@ -1,5 +1,4 @@
-/* $Id: misc.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $
- *
+/*
  * misc.c: Miscellaneous ARCS PROM routines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -13,13 +12,12 @@
 #include <asm/bootinfo.h>
 #include <asm/system.h>
 
-extern unsigned long mips_cputype;
 extern void *sgiwd93_host;
 extern void reset_wd33c93(void *instance);
 
 void prom_halt(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
@@ -29,7 +27,7 @@
 
 void prom_powerdown(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
@@ -40,7 +38,7 @@
 /* XXX is this a soft reset basically? XXX */
 void prom_restart(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
@@ -50,7 +48,7 @@
 
 void prom_reboot(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
@@ -60,7 +58,7 @@
 
 void prom_imode(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
diff -u --recursive --new-file v2.4.3/linux/arch/mips/arc/printf.c linux/arch/mips/arc/printf.c
--- v2.4.3/linux/arch/mips/arc/printf.c	Mon Feb 28 07:18:20 2000
+++ linux/arch/mips/arc/printf.c	Wed Dec 31 16:00:00 1969
@@ -1,40 +0,0 @@
-/*
- * printf.c: Putting things on the screen using SGI arcs
- *           PROM facilities.
- *
- * Copyright (C) 1996 David S. Miller (dm@sgi.com)
- *
- * $Id: printf.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/sgialib.h>
-
-static char ppbuf[1024];
-
-#ifdef CONFIG_SGI_PROM_CONSOLE
-void prom_printf(char *fmt, ...)
-#else
-void __init prom_printf(char *fmt, ...)
-#endif
-{
-	va_list args;
-	char ch, *bptr;
-	int i;
-
-	va_start(args, fmt);
-	i = vsprintf(ppbuf, fmt, args);
-
-	bptr = ppbuf;
-
-	while((ch = *(bptr++)) != 0) {
-		if(ch == '\n')
-			prom_putchar('\r');
-
-		prom_putchar(ch);
-	}
-	va_end(args);
-	return;
-}
diff -u --recursive --new-file v2.4.3/linux/arch/mips/baget/Makefile linux/arch/mips/baget/Makefile
--- v2.4.3/linux/arch/mips/baget/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/baget/Makefile	Fri Apr 13 20:26:07 2001
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.3 1999/08/13 17:07:26 harald Exp $
 #
 # Makefile for the Baget specific kernel interface routines
 # under Linux.
@@ -12,22 +11,12 @@
 all: baget.a 
 
 O_TARGET := baget.a
-O_OBJS   := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o wbflush.o
 
-ifeq ($(CONFIG_SERIAL),y)
-	OX_OBJS += vacserial.o
-else
-	ifeq ($(CONFIG_SERIAL),m)
-		MX_OBJS += vacserial.o
-	endif
-endif
-ifeq ($(CONFIG_VAC_RTC),y)
-	OX_OBJS += vacrtc.o
-else
-	ifeq ($(CONFIG_VAC_RTC),m)
-		MX_OBJS += vacrtc.o
-	endif
-endif
+export-objs		:= vacserial.o vacrtc.o
+obj-y			:= baget.o print.o setup.o time.o irq.o bagetIRQ.o \
+			   reset.o wbflush.o
+obj-$(CONFIG_SERIAL)	+= vacserial.o
+obj-$(CONFIG_VAC_RTC)	+= vacrtc.o
 
 bagetIRQ.o : bagetIRQ.S
 	$(CC) $(CFLAGS) -c -o $@ $<
diff -u --recursive --new-file v2.4.3/linux/arch/mips/baget/prom/Makefile linux/arch/mips/baget/prom/Makefile
--- v2.4.3/linux/arch/mips/baget/prom/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/baget/prom/Makefile	Fri Apr 13 20:26:07 2001
@@ -1,4 +1,4 @@
-# $Id$
+#
 # Makefile for the Baget/MIPS prom emulator library routines.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -7,9 +7,8 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-O_TARGET := bagetlib.a
-O_OBJS   := init.o
+L_TARGET := bagetlib.a
 
-all: 	$(O_TARGET)
+obj-y	:= init.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/mips/config.in linux/arch/mips/config.in
--- v2.4.3/linux/arch/mips/config.in	Thu Nov 16 12:51:28 2000
+++ linux/arch/mips/config.in	Tue Apr 17 17:19:25 2001
@@ -28,6 +28,9 @@
 bool 'Support for SGI IP22' CONFIG_SGI_IP22
 bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
 
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+
 #
 # Select some configuration options automatically for certain systems.
 #
@@ -329,7 +332,10 @@
 #   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_RTC
+   bool 'Enhanced Real Time Clock Support' CONFIG_MIPS_RTC
+
+   define_tristate CONFIG_RTC $CONFIG_MIPS_RTC
+
    endmenu
 fi
 
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5074/Makefile linux/arch/mips/ddb5074/Makefile
--- v2.4.3/linux/arch/mips/ddb5074/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/Makefile	Fri Apr 13 20:26:07 2001
@@ -8,8 +8,6 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 #
-# $Id$
-#
 
 .S.s:
 	$(CPP) $(CFLAGS) $< -o $*.s
@@ -17,6 +15,7 @@
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
 O_TARGET = ddb5074.a
-O_OBJS  = setup.o irq.o time.o prom.o pci.o pci-dma.o int-handler.o nile4.o
+
+obj-y	:= setup.o irq.o time.o prom.o pci.o int-handler.o nile4.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5074/int-handler.S linux/arch/mips/ddb5074/int-handler.S
--- v2.4.3/linux/arch/mips/ddb5074/int-handler.S	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/int-handler.S	Fri Apr 13 20:26:07 2001
@@ -7,54 +7,50 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: int-handler.S,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
-	/* A lot of complication here is taken away because:
-	 *
-	 * 1) We handle one interrupt and return, sitting in a loop
-	 *    and moving across all the pending IRQ bits in the cause
-	 *    register is _NOT_ the answer, the common case is one
-	 *    pending IRQ so optimize in that direction.
-	 *
-	 * 2) We need not check against bits in the status register
-	 *    IRQ mask, that would make this routine slow as hell.
-	 *
-	 * 3) Linux only thinks in terms of all IRQs on or all IRQs
-	 *    off, nothing in between like BSD spl() brain-damage.
-	 *
-	 * Furthermore, the IRQs on the INDY look basically (barring
-	 * software IRQs which we don't use at all) like:
-	 *
-	 *	MIPS IRQ	Source
-	 *      --------        ------
-	 *             0	Software (ignored)
-	 *             1        Software (ignored)
-	 *             2        Local IRQ level zero
-	 *             3        Local IRQ level one
-	 *             4        8254 Timer zero
-	 *             5        8254 Timer one
-	 *             6        Bus Error
-	 *             7        R4k timer (what we use)
-	 *
-	 * We handle the IRQ according to _our_ priority which is:
-	 *
-	 * Highest ----     R4k Timer
-	 *                  Local IRQ zero
-	 *                  Local IRQ one
-	 *                  Bus Error
-	 *                  8254 Timer zero
-	 * Lowest  ----     8254 Timer one
-	 *
-	 * then we just return, if multiple IRQs are pending then
-	 * we will just take another exception, big deal.
-	 */
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the INDY look basically (barring software IRQs
+ * which we don't use at all) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Local IRQ level zero
+ *             3        Local IRQ level one
+ *             4        8254 Timer zero
+ *             5        8254 Timer one
+ *             6        Bus Error
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ *                  Local IRQ zero
+ *                  Local IRQ one
+ *                  Bus Error
+ *                  8254 Timer zero
+ * Lowest  ----     8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
 
 	.text
 	.set	noreorder
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5074/irq.c linux/arch/mips/ddb5074/irq.c
--- v2.4.3/linux/arch/mips/ddb5074/irq.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/irq.c	Fri Apr 13 20:26:07 2001
@@ -3,10 +3,7 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: irq.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/signal.h>
@@ -14,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/ptrace.h>
@@ -27,7 +25,7 @@
 
 extern asmlinkage void ddbIRQ(void);
 extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs);
-extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
+extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
 
 
 void no_action(int cpl, void *dev_id, struct pt_regs *regs)
@@ -55,177 +53,174 @@
 
 static void m1543_irq_setup(void)
 {
-    /*
-     *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
-     *  the possible IO sources in the M1543 are in use by us.  We will
-     *  use the following mapping:
-     *
-     *	    IRQ1  - keyboard (default set by M1543)
-     *	    IRQ3  - reserved for UART B (default set by M1543) (note that
-     *		    the schematics for the DDB Vrc-5074 board seem to 
-     *		    indicate that IRQ3 is connected to the DS1386 
-     *		    watchdog timer interrupt output so we might have 
-     *		    a conflict)
-     *	    IRQ4  - reserved for UART A (default set by M1543)
-     *	    IRQ5  - parallel (default set by M1543)
-     *	    IRQ8  - DS1386 time of day (RTC) interrupt
-     *	    IRQ12 - mouse
-     */
- 
-    /*
-     *  Assing mouse interrupt to IRQ12 
-     */
-
-    /* Enter configuration mode */
-    outb(0x51, M1543_PNP_CONFIG);
-    outb(0x23, M1543_PNP_CONFIG);
-
-    /* Select logical device 7 (Keyboard) */
-    outb(0x07, M1543_PNP_INDEX);
-    outb(0x07, M1543_PNP_DATA);
-
-    /* Select IRQ12 */
-    outb(0x72, M1543_PNP_INDEX);
-    outb(0x0c, M1543_PNP_DATA);
-
-    /* Leave configration mode */
-    outb(0xbb, M1543_PNP_CONFIG);
+	/*
+	 *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
+	 *  the possible IO sources in the M1543 are in use by us.  We will
+	 *  use the following mapping:
+	 *
+	 *      IRQ1  - keyboard (default set by M1543)
+	 *      IRQ3  - reserved for UART B (default set by M1543) (note that
+	 *              the schematics for the DDB Vrc-5074 board seem to 
+	 *              indicate that IRQ3 is connected to the DS1386 
+	 *              watchdog timer interrupt output so we might have 
+	 *              a conflict)
+	 *      IRQ4  - reserved for UART A (default set by M1543)
+	 *      IRQ5  - parallel (default set by M1543)
+	 *      IRQ8  - DS1386 time of day (RTC) interrupt
+	 *      IRQ12 - mouse
+	 */
+
+	/*
+	 *  Assing mouse interrupt to IRQ12 
+	 */
+
+	/* Enter configuration mode */
+	outb(0x51, M1543_PNP_CONFIG);
+	outb(0x23, M1543_PNP_CONFIG);
+
+	/* Select logical device 7 (Keyboard) */
+	outb(0x07, M1543_PNP_INDEX);
+	outb(0x07, M1543_PNP_DATA);
+
+	/* Select IRQ12 */
+	outb(0x72, M1543_PNP_INDEX);
+	outb(0x0c, M1543_PNP_DATA);
+
+	/* Leave configration mode */
+	outb(0xbb, M1543_PNP_CONFIG);
 
 
-    /* Initialize the 8259 PIC in the M1543 */
-    i8259_init();
+	/* Initialize the 8259 PIC in the M1543 */
+	i8259_init();
 
-    /* Enable the interrupt cascade */
-    nile4_enable_irq(NILE4_INT_INTE);
+	/* Enable the interrupt cascade */
+	nile4_enable_irq(NILE4_INT_INTE);
 
-    request_region(M1543_PNP_CONFIG, 2, "M1543 config");
-    request_region(M1543_INT1_MASTER_ELCR, 2, "pic ELCR");
+	request_region(M1543_PNP_CONFIG, 2, "M1543 config");
+	request_region(M1543_INT1_MASTER_ELCR, 2, "pic ELCR");
 }
 
 static void nile4_irq_setup(void)
 {
-    int i;
+	int i;
 
-    /* Map all interrupts to CPU int #0 */
-    nile4_map_irq_all(0);
+	/* Map all interrupts to CPU int #0 */
+	nile4_map_irq_all(0);
 
-    /* PCI INTA#-E# must be level triggered */
-    nile4_set_pci_irq_level_or_edge(0, 1);
-    nile4_set_pci_irq_level_or_edge(1, 1);
-    nile4_set_pci_irq_level_or_edge(2, 1);
-    nile4_set_pci_irq_level_or_edge(3, 1);
-    nile4_set_pci_irq_level_or_edge(4, 1);
-
-    /* PCI INTA#-D# must be active low, INTE# must be active high */
-    nile4_set_pci_irq_polarity(0, 0);
-    nile4_set_pci_irq_polarity(1, 0);
-    nile4_set_pci_irq_polarity(2, 0);
-    nile4_set_pci_irq_polarity(3, 0);
-    nile4_set_pci_irq_polarity(4, 1);
+	/* PCI INTA#-E# must be level triggered */
+	nile4_set_pci_irq_level_or_edge(0, 1);
+	nile4_set_pci_irq_level_or_edge(1, 1);
+	nile4_set_pci_irq_level_or_edge(2, 1);
+	nile4_set_pci_irq_level_or_edge(3, 1);
+	nile4_set_pci_irq_level_or_edge(4, 1);
+
+	/* PCI INTA#-D# must be active low, INTE# must be active high */
+	nile4_set_pci_irq_polarity(0, 0);
+	nile4_set_pci_irq_polarity(1, 0);
+	nile4_set_pci_irq_polarity(2, 0);
+	nile4_set_pci_irq_polarity(3, 0);
+	nile4_set_pci_irq_polarity(4, 1);
 
-    for (i = 0; i < 16; i++)
-	nile4_clear_irq(i);
+	for (i = 0; i < 16; i++)
+		nile4_clear_irq(i);
 
-    /* Enable CPU int #0 */
-    nile4_enable_irq_output(0);
+	/* Enable CPU int #0 */
+	nile4_enable_irq_output(0);
 
-    request_mem_region(NILE4_BASE, NILE4_SIZE, "Nile 4");
+	request_mem_region(NILE4_BASE, NILE4_SIZE, "Nile 4");
 }
 
 
 /*
  * IRQ2 is cascade interrupt to second interrupt controller
  */
-
-static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL };
+static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
 
 
 void disable_irq(unsigned int irq_nr)
 {
-    if (is_i8259_irq(irq_nr))
-	i8259_disable_irq(irq_nr);
-    else
-	nile4_disable_irq(irq_to_nile4(irq_nr));
+	if (is_i8259_irq(irq_nr))
+		i8259_disable_irq(irq_nr);
+	else
+		nile4_disable_irq(irq_to_nile4(irq_nr));
 }
 
 void enable_irq(unsigned int irq_nr)
 {
-    if (is_i8259_irq(irq_nr))
-	i8259_enable_irq(irq_nr);
-    else
-	nile4_enable_irq(irq_to_nile4(irq_nr));
+	if (is_i8259_irq(irq_nr))
+		i8259_enable_irq(irq_nr);
+	else
+		nile4_enable_irq(irq_to_nile4(irq_nr));
 }
 
 int table[16] = { 0, };
 
 void ddb_local0_irqdispatch(struct pt_regs *regs)
 {
-    u32 mask;
-    int nile4_irq;
+	u32 mask;
+	int nile4_irq;
 #if 1
-    volatile static int nesting = 0;
-    if (nesting++ == 0)
-	ddb5074_led_d3(1);
-    ddb5074_led_hex(nesting < 16 ? nesting : 15);
+	volatile static int nesting = 0;
+	if (nesting++ == 0)
+		ddb5074_led_d3(1);
+	ddb5074_led_hex(nesting < 16 ? nesting : 15);
 #endif
 
-    mask = nile4_get_irq_stat(0);
-    nile4_clear_irq_mask(mask);
+	mask = nile4_get_irq_stat(0);
+	nile4_clear_irq_mask(mask);
 
-    /* Handle the timer interrupt first */
-    if (mask & (1<<NILE4_INT_GPT)) {
-	nile4_disable_irq(NILE4_INT_GPT);
-	do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
-	nile4_enable_irq(NILE4_INT_GPT);
-	mask &= ~(1<<NILE4_INT_GPT);
-    }
-    for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
-	if (mask & 1) {
-	    nile4_disable_irq(nile4_irq);
-	    if (nile4_irq == NILE4_INT_INTE) {
-		int i8259_irq = nile4_i8259_iack();
-		i8259_do_irq(i8259_irq, regs);
-	    } else
-		do_IRQ(nile4_to_irq(nile4_irq), regs);
-	    nile4_enable_irq(nile4_irq);
+	/* Handle the timer interrupt first */
+	if (mask & (1 << NILE4_INT_GPT)) {
+		nile4_disable_irq(NILE4_INT_GPT);
+		do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
+		nile4_enable_irq(NILE4_INT_GPT);
+		mask &= ~(1 << NILE4_INT_GPT);
 	}
-
+	for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
+		if (mask & 1) {
+			nile4_disable_irq(nile4_irq);
+			if (nile4_irq == NILE4_INT_INTE) {
+				int i8259_irq = nile4_i8259_iack();
+				i8259_do_irq(i8259_irq, regs);
+			} else
+				do_IRQ(nile4_to_irq(nile4_irq), regs);
+			nile4_enable_irq(nile4_irq);
+		}
 #if 1
-    if (--nesting == 0)
-	ddb5074_led_d3(0);
-    ddb5074_led_hex(nesting < 16 ? nesting : 15);
+	if (--nesting == 0)
+		ddb5074_led_d3(0);
+	ddb5074_led_hex(nesting < 16 ? nesting : 15);
 #endif
 }
 
 void ddb_local1_irqdispatch(void)
 {
-    printk("ddb_local1_irqdispatch called\n");
+	printk("ddb_local1_irqdispatch called\n");
 }
 
 void ddb_buserror_irq(void)
 {
-    printk("ddb_buserror_irq called\n");
+	printk("ddb_buserror_irq called\n");
 }
 
 void ddb_8254timer_irq(void)
 {
-    printk("ddb_8254timer_irq called\n");
+	printk("ddb_8254timer_irq called\n");
 }
 
 void __init ddb_irq_setup(void)
 {
 #ifdef CONFIG_REMOTE_DEBUG
-    if (remote_debug)
-	set_debug_traps();
-    breakpoint(); /* you may move this line to whereever you want :-) */
+	if (remote_debug)
+		set_debug_traps();
+	breakpoint();		/* you may move this line to whereever you want :-) */
 #endif
-    request_region(0x20, 0x20, "pic1");
-    request_region(0xa0, 0x20, "pic2");
-    i8259_setup_irq(2, &irq2);
+	request_region(0x20, 0x20, "pic1");
+	request_region(0xa0, 0x20, "pic2");
+	i8259_setup_irq(2, &irq2);
 
-    nile4_irq_setup();
-    m1543_irq_setup();
+	nile4_irq_setup();
+	m1543_irq_setup();
 
-    set_except_vector(0, ddbIRQ);
+	set_except_vector(0, ddbIRQ);
 }
-
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5074/nile4.c linux/arch/mips/ddb5074/nile4.c
--- v2.4.3/linux/arch/mips/ddb5074/nile4.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/nile4.c	Fri Apr 13 20:26:07 2001
@@ -3,292 +3,290 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id$
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
+
 #include <asm/nile4.h>
 
 
-    /*
-     *  Physical Device Address Registers
-     *
-     *  Note: 32 bit addressing only!
-     */
-
-void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width, int on_memory_bus,
-		    int visible)
-{
-    u32 maskbits;
-    u32 widthbits;
-
-    if (pdar > NILE4_BOOTCS || (pdar & 7)) {
-	printk("nile4_set_pdar: invalid pdar %d\n", pdar);
-	return;
-    }
-    if (pdar == NILE4_INTCS && size != 0x00200000) {
-	printk("nile4_set_pdar: INTCS size must be 2 MB\n");
-	return;
-    }
-    switch (size) {
-#if 0	/* We don't support 4 GB yet */
+/*
+ *  Physical Device Address Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
+void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
+		    int on_memory_bus, int visible)
+{
+	u32 maskbits;
+	u32 widthbits;
+
+	if (pdar > NILE4_BOOTCS || (pdar & 7)) {
+		printk("nile4_set_pdar: invalid pdar %d\n", pdar);
+		return;
+	}
+	if (pdar == NILE4_INTCS && size != 0x00200000) {
+		printk("nile4_set_pdar: INTCS size must be 2 MB\n");
+		return;
+	}
+	switch (size) {
+#if 0				/* We don't support 4 GB yet */
 	case 0x100000000:	/* 4 GB */
-	    maskbits = 4;
-	    break;
+		maskbits = 4;
+		break;
 #endif
 	case 0x80000000:	/* 2 GB */
-	    maskbits = 5;
-	    break;
+		maskbits = 5;
+		break;
 	case 0x40000000:	/* 1 GB */
-	    maskbits = 6;
-	    break;
+		maskbits = 6;
+		break;
 	case 0x20000000:	/* 512 MB */
-	    maskbits = 7;
-	    break;
+		maskbits = 7;
+		break;
 	case 0x10000000:	/* 256 MB */
-	    maskbits = 8;
-	    break;
+		maskbits = 8;
+		break;
 	case 0x08000000:	/* 128 MB */
-	    maskbits = 9;
-	    break;
+		maskbits = 9;
+		break;
 	case 0x04000000:	/* 64 MB */
-	    maskbits = 10;
-	    break;
+		maskbits = 10;
+		break;
 	case 0x02000000:	/* 32 MB */
-	    maskbits = 11;
-	    break;
+		maskbits = 11;
+		break;
 	case 0x01000000:	/* 16 MB */
-	    maskbits = 12;
-	    break;
+		maskbits = 12;
+		break;
 	case 0x00800000:	/* 8 MB */
-	    maskbits = 13;
-	    break;
+		maskbits = 13;
+		break;
 	case 0x00400000:	/* 4 MB */
-	    maskbits = 14;
-	    break;
+		maskbits = 14;
+		break;
 	case 0x00200000:	/* 2 MB */
-	    maskbits = 15;
-	    break;
-	case 0:			/* OFF */
-	    maskbits = 0;
-	    break;
+		maskbits = 15;
+		break;
+	case 0:		/* OFF */
+		maskbits = 0;
+		break;
 	default:
-	    printk("nile4_set_pdar: unsupported size %p\n", (void *)size);
-	    return;
-    }
-    switch (width) {
+		printk("nile4_set_pdar: unsupported size %p\n", (void *) size);
+		return;
+	}
+	switch (width) {
 	case 8:
-	    widthbits = 0;
-	    break;
+		widthbits = 0;
+		break;
 	case 16:
-	    widthbits = 1;
-	    break;
+		widthbits = 1;
+		break;
 	case 32:
-	    widthbits = 2;
-	    break;
+		widthbits = 2;
+		break;
 	case 64:
-	    widthbits = 3;
-	    break;
+		widthbits = 3;
+		break;
 	default:
-	    printk("nile4_set_pdar: unsupported width %d\n", width);
-	    return;
-    }
-    nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
-    		      (visible ? 0x20 : 0) | (widthbits << 6) |
-		      (phys & 0xffe00000));
-    nile4_out32(pdar+4, 0);
-    /*
-     *  When programming a PDAR, the register should be read immediately after
-     *  writing it. This ensures that address decoders are properly configured.
-     */
-    (void)nile4_in32(pdar);
-    (void)nile4_in32(pdar+4);
+		printk("nile4_set_pdar: unsupported width %d\n", width);
+		return;
+	}
+	nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
+		    (visible ? 0x20 : 0) | (widthbits << 6) |
+		    (phys & 0xffe00000));
+	nile4_out32(pdar + 4, 0);
+	/*
+	 * When programming a PDAR, the register should be read immediately
+	 * after writing it. This ensures that address decoders are properly
+	 * configured.
+	 */
+	nile4_in32(pdar);
+	nile4_in32(pdar + 4);
 }
 
 
-    /*
-     *  PCI Master Registers
-     *
-     *  Note: 32 bit addressing only!
-     */
-
+/*
+ *  PCI Master Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
 void nile4_set_pmr(u32 pmr, u32 type, u32 addr)
 {
-    if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
-	printk("nile4_set_pmr: invalid pmr %d\n", pmr);
-	return;
-    }
-    switch (type) {
+	if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
+		printk("nile4_set_pmr: invalid pmr %d\n", pmr);
+		return;
+	}
+	switch (type) {
 	case NILE4_PCICMD_IACK:	/* PCI Interrupt Acknowledge */
 	case NILE4_PCICMD_IO:	/* PCI I/O Space */
 	case NILE4_PCICMD_MEM:	/* PCI Memory Space */
 	case NILE4_PCICMD_CFG:	/* PCI Configuration Space */
-	    break;
+		break;
 	default:
-	    printk("nile4_set_pmr: invalid type %d\n", type);
-	    return;
-    }
-    nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
-    nile4_out32(pmr+4, 0);
+		printk("nile4_set_pmr: invalid type %d\n", type);
+		return;
+	}
+	nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
+	nile4_out32(pmr + 4, 0);
 }
 
 
-    /*
-     *  Interrupt Programming
-     */
-
+/*
+ *  Interrupt Programming
+ */
 void nile4_map_irq(int nile4_irq, int cpu_irq)
 {
-    u32 offset, t;
+	u32 offset, t;
 
-    offset = NILE4_INTCTRL;
-    if (nile4_irq >= 8) {
-	offset += 4;
-	nile4_irq -= 8;
-    }
-    t = nile4_in32(offset);
-    t &= ~(7 << (nile4_irq*4));
-    t |= cpu_irq << (nile4_irq*4);
-    nile4_out32(offset, t);
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t &= ~(7 << (nile4_irq * 4));
+	t |= cpu_irq << (nile4_irq * 4);
+	nile4_out32(offset, t);
 }
 
 void nile4_map_irq_all(int cpu_irq)
 {
-    u32 all, t;
-    
-    all = cpu_irq;
-    all |= all << 4;
-    all |= all << 8;
-    all |= all << 16;
-    t = nile4_in32(NILE4_INTCTRL);
-    t &= 0x88888888;
-    t |= all;
-    nile4_out32(NILE4_INTCTRL, t);
-    t = nile4_in32(NILE4_INTCTRL+4);
-    t &= 0x88888888;
-    t |= all;
-    nile4_out32(NILE4_INTCTRL+4, t);
+	u32 all, t;
+
+	all = cpu_irq;
+	all |= all << 4;
+	all |= all << 8;
+	all |= all << 16;
+	t = nile4_in32(NILE4_INTCTRL);
+	t &= 0x88888888;
+	t |= all;
+	nile4_out32(NILE4_INTCTRL, t);
+	t = nile4_in32(NILE4_INTCTRL + 4);
+	t &= 0x88888888;
+	t |= all;
+	nile4_out32(NILE4_INTCTRL + 4, t);
 }
 
 void nile4_enable_irq(int nile4_irq)
 {
-    u32 offset, t;
+	u32 offset, t;
 
-    offset = NILE4_INTCTRL;
-    if (nile4_irq >= 8) {
-	offset += 4;
-	nile4_irq -= 8;
-    }
-    t = nile4_in32(offset);
-    t |= 8 << (nile4_irq*4);
-    nile4_out32(offset, t);
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t |= 8 << (nile4_irq * 4);
+	nile4_out32(offset, t);
 }
 
 void nile4_disable_irq(int nile4_irq)
 {
-    u32 offset, t;
+	u32 offset, t;
 
-    offset = NILE4_INTCTRL;
-    if (nile4_irq >= 8) {
-	offset += 4;
-	nile4_irq -= 8;
-    }
-    t = nile4_in32(offset);
-    t &= ~(8 << (nile4_irq*4));
-    nile4_out32(offset, t);
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t &= ~(8 << (nile4_irq * 4));
+	nile4_out32(offset, t);
 }
 
 void nile4_disable_irq_all(void)
 {
-    nile4_out32(NILE4_INTCTRL, 0);
-    nile4_out32(NILE4_INTCTRL+4, 0);
+	nile4_out32(NILE4_INTCTRL, 0);
+	nile4_out32(NILE4_INTCTRL + 4, 0);
 }
 
 u16 nile4_get_irq_stat(int cpu_irq)
 {
-    return nile4_in16(NILE4_INTSTAT0+cpu_irq*2);
+	return nile4_in16(NILE4_INTSTAT0 + cpu_irq * 2);
 }
 
 void nile4_enable_irq_output(int cpu_irq)
 {
-    u32 t;
+	u32 t;
 
-    t = nile4_in32(NILE4_INTSTAT1+4);
-    t |= 1 << (16+cpu_irq);
-    nile4_out32(NILE4_INTSTAT1, t);
+	t = nile4_in32(NILE4_INTSTAT1 + 4);
+	t |= 1 << (16 + cpu_irq);
+	nile4_out32(NILE4_INTSTAT1, t);
 }
 
 void nile4_disable_irq_output(int cpu_irq)
 {
-    u32 t;
+	u32 t;
 
-    t = nile4_in32(NILE4_INTSTAT1+4);
-    t &= ~(1 << (16+cpu_irq));
-    nile4_out32(NILE4_INTSTAT1, t);
+	t = nile4_in32(NILE4_INTSTAT1 + 4);
+	t &= ~(1 << (16 + cpu_irq));
+	nile4_out32(NILE4_INTSTAT1, t);
 }
 
 void nile4_set_pci_irq_polarity(int pci_irq, int high)
 {
-    u32 t;
+	u32 t;
 
-    t = nile4_in32(NILE4_INTPPES);
-    if (high)
-	t &= ~(1 << (pci_irq*2));
-    else
-	t |= 1 << (pci_irq*2);
-    nile4_out32(NILE4_INTPPES, t);
+	t = nile4_in32(NILE4_INTPPES);
+	if (high)
+		t &= ~(1 << (pci_irq * 2));
+	else
+		t |= 1 << (pci_irq * 2);
+	nile4_out32(NILE4_INTPPES, t);
 }
 
 void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
 {
-    u32 t;
+	u32 t;
 
-    t = nile4_in32(NILE4_INTPPES);
-    if (level)
-	t |= 2 << (pci_irq*2);
-    else
-	t &= ~(2 << (pci_irq*2));
-    nile4_out32(NILE4_INTPPES, t);
+	t = nile4_in32(NILE4_INTPPES);
+	if (level)
+		t |= 2 << (pci_irq * 2);
+	else
+		t &= ~(2 << (pci_irq * 2));
+	nile4_out32(NILE4_INTPPES, t);
 }
 
 void nile4_clear_irq(int nile4_irq)
 {
-    nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
+	nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
 }
 
 void nile4_clear_irq_mask(u32 mask)
 {
-    nile4_out32(NILE4_INTCLR, mask);
+	nile4_out32(NILE4_INTCLR, mask);
 }
 
 u8 nile4_i8259_iack(void)
 {
-    u8 irq;
+	u8 irq;
 
-    /* Set window 0 for interrupt acknowledge */
-    nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
-    irq = *(volatile u8 *)NILE4_PCI_IACK_BASE;
-    /* Set window 0 for PCI I/O space */
-    nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
-    return irq;
+	/* Set window 0 for interrupt acknowledge */
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
+	irq = *(volatile u8 *) NILE4_PCI_IACK_BASE;
+	/* Set window 0 for PCI I/O space */
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
+	return irq;
 }
 
 #if 0
 void nile4_dump_irq_status(void)
 {
-    printk("CPUSTAT = %p:%p\n", (void *)nile4_in32(NILE4_CPUSTAT+4),
-    				(void *)nile4_in32(NILE4_CPUSTAT));
-    printk("INTCTRL = %p:%p\n", (void *)nile4_in32(NILE4_INTCTRL+4),
-    				(void *)nile4_in32(NILE4_INTCTRL));
-    printk("INTSTAT0 = %p:%p\n", (void *)nile4_in32(NILE4_INTSTAT0+4),
-    				(void *)nile4_in32(NILE4_INTSTAT0));
-    printk("INTSTAT1 = %p:%p\n", (void *)nile4_in32(NILE4_INTSTAT1+4),
-    				(void *)nile4_in32(NILE4_INTSTAT1));
-    printk("INTCLR = %p:%p\n", (void *)nile4_in32(NILE4_INTCLR+4),
-    				(void *)nile4_in32(NILE4_INTCLR));
-    printk("INTPPES = %p:%p\n", (void *)nile4_in32(NILE4_INTPPES+4),
-    				(void *)nile4_in32(NILE4_INTPPES));
+	printk("CPUSTAT = %p:%p\n", (void *) nile4_in32(NILE4_CPUSTAT + 4),
+	       (void *) nile4_in32(NILE4_CPUSTAT));
+	printk("INTCTRL = %p:%p\n", (void *) nile4_in32(NILE4_INTCTRL + 4),
+	       (void *) nile4_in32(NILE4_INTCTRL));
+	printk("INTSTAT0 = %p:%p\n",
+	       (void *) nile4_in32(NILE4_INTSTAT0 + 4),
+	       (void *) nile4_in32(NILE4_INTSTAT0));
+	printk("INTSTAT1 = %p:%p\n",
+	       (void *) nile4_in32(NILE4_INTSTAT1 + 4),
+	       (void *) nile4_in32(NILE4_INTSTAT1));
+	printk("INTCLR = %p:%p\n", (void *) nile4_in32(NILE4_INTCLR + 4),
+	       (void *) nile4_in32(NILE4_INTCLR));
+	printk("INTPPES = %p:%p\n", (void *) nile4_in32(NILE4_INTPPES + 4),
+	       (void *) nile4_in32(NILE4_INTPPES));
 }
 #endif
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5074/pci-dma.c linux/arch/mips/ddb5074/pci-dma.c
--- v2.4.3/linux/arch/mips/ddb5074/pci-dma.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/pci-dma.c	Wed Dec 31 16:00:00 1969
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2000   Ani Joshi <ajoshi@unixbox.com>
- *
- *
- * Dynamic DMA mapping support.
- *
- * swiped from i386, and cloned for MIPS by Geert.
- *
- */
-
-#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_handle = virt_to_bus(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)vaddr, get_order(size));
-}
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5074/pci.c linux/arch/mips/ddb5074/pci.c
--- v2.4.3/linux/arch/mips/ddb5074/pci.c	Mon Nov 27 17:51:34 2000
+++ linux/arch/mips/ddb5074/pci.c	Fri Apr 13 20:26:07 2001
@@ -4,313 +4,325 @@
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Albert Dorofeev <albert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: pci.c,v 1.4 2000/02/18 00:02:17 ralf Exp $
  */
-
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
-#include <asm-mips/nile4.h>
+
+#include <asm/nile4.h>
 
 
 static u32 nile4_pre_pci_access0(int slot_num)
 {
-    u32 pci_addr = 0;
-    u32 virt_addr = NILE4_PCI_CFG_BASE;
+	u32 pci_addr = 0;
+	u32 virt_addr = NILE4_PCI_CFG_BASE;
 
-    /* Set window 1 address 8000000 - 64 bit - 2 MB (PCI config space) */
-    nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x00200000, 64, 0, 0);
-    if (slot_num > 2)
-	pci_addr = 0x00040000 << slot_num;
-    else
-	virt_addr += 0x00040000 << slot_num;
-    nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr);
-    return virt_addr;
+	/* Set window 1 address 8000000 - 64 bit - 2 MB (PCI config space) */
+	nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x00200000, 64, 0,
+		       0);
+	if (slot_num > 2)
+		pci_addr = 0x00040000 << slot_num;
+	else
+		virt_addr += 0x00040000 << slot_num;
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr);
+	return virt_addr;
 }
 
 static void nile4_post_pci_access0(void)
 {
-    /* Set window 1 back to address 8000000 - 64 bit - 128 MB (PCI IO space) */
-    nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE), 0x08000000, 64,
-    		   1, 1);
-    nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
+	/*
+	 * Set window 1 back to address 8000000 - 64 bit - 128 MB
+	 * (PCI IO space)
+	 */
+	nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE),
+		       0x08000000, 64, 1, 1);
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
 }
 
 
-static int nile4_pci_read_config_dword( struct pci_dev *dev,
-				int where, u32 *val)
+static int nile4_pci_read_config_dword(struct pci_dev *dev,
+				       int where, u32 * val)
 {
-    int slot_num, func_num;
-    u32 base;
-
-    /*
-     *  For starters let's do configuration cycle 0 only (one bus only)
-     */
-    if (dev->bus->number)
-	return PCIBIOS_FUNC_NOT_SUPPORTED;
+	int slot_num, func_num;
+	u32 base;
 
-    slot_num = PCI_SLOT(dev->devfn);
-    func_num = PCI_FUNC(dev->devfn);
-    if (slot_num == 5) {
 	/*
-	 *  This is Nile 4 and it will crash if we access it like other
-	 *   devices
+	 *  For starters let's do configuration cycle 0 only (one bus only)
 	 */
-	*val = nile4_in32(NILE4_PCI_BASE + where);
+	if (dev->bus->number)
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	slot_num = PCI_SLOT(dev->devfn);
+	func_num = PCI_FUNC(dev->devfn);
+	if (slot_num == 5) {
+		/*
+		 * This is Nile 4 and it will crash if we access it like other
+		 * devices
+		 */
+		*val = nile4_in32(NILE4_PCI_BASE + where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	base = nile4_pre_pci_access0(slot_num);
+	*val =
+	    *((volatile u32 *) (base + (func_num << 8) + (where & 0xfc)));
+	nile4_post_pci_access0();
 	return PCIBIOS_SUCCESSFUL;
-    }
-    base = nile4_pre_pci_access0(slot_num);
-    *val = *((volatile u32 *)(base + (func_num << 8) + (where & 0xfc)));
-    nile4_post_pci_access0();
-    return PCIBIOS_SUCCESSFUL;
 }
 
 static int nile4_pci_write_config_dword(struct pci_dev *dev, int where,
 					u32 val)
 {
-    int slot_num, func_num;
-    u32 base;
+	int slot_num, func_num;
+	u32 base;
 
-    /*
-     *  For starters let's do configuration cycle 0 only (one bus only)
-     */
-    if (dev->bus->number)
-	return PCIBIOS_FUNC_NOT_SUPPORTED;
-
-    slot_num = PCI_SLOT(dev->devfn);
-    func_num = PCI_FUNC(dev->devfn);
-    if (slot_num == 5) {
 	/*
-	 *  This is Nile 4 and it will crash if we access it like other
-	 *   devices
+	 * For starters let's do configuration cycle 0 only (one bus only)
 	 */
-	nile4_out32(NILE4_PCI_BASE + where, val);
+	if (dev->bus->number)
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	slot_num = PCI_SLOT(dev->devfn);
+	func_num = PCI_FUNC(dev->devfn);
+	if (slot_num == 5) {
+		/*
+		 * This is Nile 4 and it will crash if we access it like other
+		 * devices
+		 */
+		nile4_out32(NILE4_PCI_BASE + where, val);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	base = nile4_pre_pci_access0(slot_num);
+	*((volatile u32 *) (base + (func_num << 8) + (where & 0xfc))) =
+	    val;
+	nile4_post_pci_access0();
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_read_config_word(struct pci_dev *dev, int where,
+				      u16 * val)
+{
+	int status;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xffff;
 	return PCIBIOS_SUCCESSFUL;
-    }
-    base = nile4_pre_pci_access0(slot_num);
-    *((volatile u32 *)(base + (func_num << 8) + (where & 0xfc))) = val;
-    nile4_post_pci_access0();
-    return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
-{
-    int status;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-	return status;
-    if (where & 2)
-	result >>= 16;
-    *val = result & 0xffff;
-    return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
-{
-    int status;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-	return status;
-    if (where & 1)
-	result >>= 8;
-    if (where & 2)
-	result >>= 16;
-    *val = result & 0xff;
-    return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
-{
-    int status, shift = 0;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-	return status;
-    if (where & 2)
-	shift += 16;
-    result &= ~(0xffff << shift);
-    result |= val << shift;
-    return nile4_pci_write_config_dword(dev, where, result);
-}
-
-static int nile4_pci_write_config_byte( struct pci_dev *dev, int where, u8 val)
-{
-    int status, shift = 0;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-	return status;
-    if (where & 2)
-	shift += 16;
-    if (where & 1)
-	shift += 8;
-    result &= ~(0xff << shift);
-    result |= val << shift;
-    return nile4_pci_write_config_dword(dev, where, result);
+}
+
+static int nile4_pci_read_config_byte(struct pci_dev *dev, int where,
+				      u8 * val)
+{
+	int status;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 1)
+		result >>= 8;
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xff;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_write_config_word(struct pci_dev *dev, int where,
+				       u16 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		shift += 16;
+	result &= ~(0xffff << shift);
+	result |= val << shift;
+	return nile4_pci_write_config_dword(dev, where, result);
+}
+
+static int nile4_pci_write_config_byte(struct pci_dev *dev, int where,
+				       u8 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		shift += 16;
+	if (where & 1)
+		shift += 8;
+	result &= ~(0xff << shift);
+	result |= val << shift;
+	return nile4_pci_write_config_dword(dev, where, result);
 }
 
 struct pci_ops nile4_pci_ops = {
-    nile4_pci_read_config_byte,
-    nile4_pci_read_config_word,
-    nile4_pci_read_config_dword,
-    nile4_pci_write_config_byte,
-    nile4_pci_write_config_word,
-    nile4_pci_write_config_dword
+	nile4_pci_read_config_byte,
+	nile4_pci_read_config_word,
+	nile4_pci_read_config_dword,
+	nile4_pci_write_config_byte,
+	nile4_pci_write_config_word,
+	nile4_pci_write_config_dword
 };
 
 struct {
-    struct resource ram;
-    struct resource flash;
-    struct resource isa_io;
-    struct resource pci_io;
-    struct resource isa_mem;
-    struct resource pci_mem;
-    struct resource nile4;
-    struct resource boot;
+	struct resource ram;
+	struct resource flash;
+	struct resource isa_io;
+	struct resource pci_io;
+	struct resource isa_mem;
+	struct resource pci_mem;
+	struct resource nile4;
+	struct resource boot;
 } ddb5074_resources = {
-    { "RAM", 0x00000000, 0x03ffffff,
-      IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
-    { "Flash ROM", 0x04000000, 0x043fffff },
-    { "Nile4 ISA I/O", 0x06000000, 0x060fffff },
-    { "Nile4 PCI I/O", 0x06100000, 0x07ffffff },
-    { "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM },
-    { "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM },
-    { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff,
-      IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
-    { "Boot ROM", 0x1fc00000, 0x1fffffff }
+	{ "RAM", 0x00000000, 0x03ffffff,
+	  IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64},
+	{ "Flash ROM", 0x04000000, 0x043fffff},
+	{ "Nile4 ISA I/O", 0x06000000, 0x060fffff},
+	{ "Nile4 PCI I/O", 0x06100000, 0x07ffffff},
+	{ "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM},
+	{ "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM},
+	{ "Nile4 ctrl", 0x1fa00000, 0x1fbfffff,
+	  IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64},
+	{ "Boot ROM", 0x1fc00000, 0x1fffffff}
 };
 
 static void __init ddb5074_pci_fixup(void)
 {
-    struct pci_dev *dev;
+	struct pci_dev *dev;
 
-    pci_for_each_dev(dev) {
-	if (dev->vendor == PCI_VENDOR_ID_NEC &&
-	    dev->device == PCI_DEVICE_ID_NEC_NILE4) {
-	    /*
-	     *  The first 64-bit PCI base register should point to the Nile4
-	     *  control registers. Unfortunately this isn't the case, so we fix
-	     *  it ourselves. This allows the serial driver to find the UART.
-	     */
-	    dev->resource[0] = ddb5074_resources.nile4;
-	    request_resource(&iomem_resource, &dev->resource[0]);
-	    /*
-	     *  The second 64-bit PCI base register points to the first memory
-	     *  bank. Unfortunately the address is wrong, so we fix it (again).
-	     */
-	    dev->resource[2] = ddb5074_resources.ram;
-	    request_resource(&iomem_resource, &dev->resource[2]);
-	} else if (dev->vendor == PCI_VENDOR_ID_AL &&
-		   dev->device == PCI_DEVICE_ID_AL_M7101) {
-	    /*
-	     *  It's nice to have the LEDs on the GPIO pins available for
-	     *  debugging
-	     */
-	    extern struct pci_dev *pci_pmu;
-	    u8 t8;
-
-	    pci_pmu = dev;		/* for LEDs D2 and D3 */
-	    /* Program the lines for LEDs D2 and D3 to output */
-	    nile4_pci_read_config_byte(dev, 0x7d, &t8);
-	    t8 |= 0xc0;
-	    nile4_pci_write_config_byte(dev, 0x7d, t8);
-	    /* Turn LEDs D2 and D3 off */
-	    nile4_pci_read_config_byte(dev, 0x7e, &t8);
-	    t8 |= 0xc0;
-	    nile4_pci_write_config_byte(dev, 0x7e, t8);
+	pci_for_each_dev(dev) {
+		if (dev->vendor == PCI_VENDOR_ID_NEC &&
+		    dev->device == PCI_DEVICE_ID_NEC_NILE4) {
+			/*
+			 * The first 64-bit PCI base register should point to
+			 * the Nile4 control registers. Unfortunately this
+			 * isn't the case, so we fix it ourselves. This allows
+			 * the serial driver to find the UART.
+			 */
+			dev->resource[0] = ddb5074_resources.nile4;
+			request_resource(&iomem_resource,
+					 &dev->resource[0]);
+			/*
+			 * The second 64-bit PCI base register points to the
+			 * first memory bank. Unfortunately the address is
+			 * wrong, so we fix it (again).
+			 */
+			dev->resource[2] = ddb5074_resources.ram;
+			request_resource(&iomem_resource,
+					 &dev->resource[2]);
+		} else if (dev->vendor == PCI_VENDOR_ID_AL
+			   && dev->device == PCI_DEVICE_ID_AL_M7101) {
+			/*
+			 * It's nice to have the LEDs on the GPIO pins
+			 * available for debugging
+			 */
+			extern struct pci_dev *pci_pmu;
+			u8 t8;
+
+			pci_pmu = dev;	/* for LEDs D2 and D3 */
+			/* Program the lines for LEDs D2 and D3 to output */
+			nile4_pci_read_config_byte(dev, 0x7d, &t8);
+			t8 |= 0xc0;
+			nile4_pci_write_config_byte(dev, 0x7d, t8);
+			/* Turn LEDs D2 and D3 off */
+			nile4_pci_read_config_byte(dev, 0x7e, &t8);
+			t8 |= 0xc0;
+			nile4_pci_write_config_byte(dev, 0x7e, t8);
+		}
 	}
-    }
 }
 
 static void __init pcibios_fixup_irqs(void)
 {
-    struct pci_dev *dev;
-    int slot_num;
+	struct pci_dev *dev;
+	int slot_num;
 
-    pci_for_each_dev(dev) {
-	slot_num = PCI_SLOT(dev->devfn);
-	switch (slot_num) {
-	    case 0:
-		dev->irq = nile4_to_irq(NILE4_INT_INTE);
-		break;
-	    case 1:
-		dev->irq = nile4_to_irq(NILE4_INT_INTA);
-		break;
-	    case 2:	/* slot 1 */
-		dev->irq = nile4_to_irq(NILE4_INT_INTA);
-		break;
-	    case 3:	/* slot 2 */
-		dev->irq = nile4_to_irq(NILE4_INT_INTB);
-		break;
-	    case 4:	/* slot 3 */
-		dev->irq = nile4_to_irq(NILE4_INT_INTC);
-		break;
-	    case 5:
-		/*
-		 * Fixup so the serial driver can use the UART
-		 */
-		dev->irq = nile4_to_irq(NILE4_INT_UART);
-		break;
-	    case 13:
-		dev->irq = nile4_to_irq(NILE4_INT_INTE);
-		break;
-	    default:
-		break;
+	pci_for_each_dev(dev) {
+		slot_num = PCI_SLOT(dev->devfn);
+		switch (slot_num) {
+		case 0:
+			dev->irq = nile4_to_irq(NILE4_INT_INTE);
+			break;
+		case 1:
+			dev->irq = nile4_to_irq(NILE4_INT_INTA);
+			break;
+		case 2:	/* slot 1 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTA);
+			break;
+		case 3:	/* slot 2 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTB);
+			break;
+		case 4:	/* slot 3 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTC);
+			break;
+		case 5:
+			/*
+			 * Fixup so the serial driver can use the UART
+			 */
+			dev->irq = nile4_to_irq(NILE4_INT_UART);
+			break;
+		case 13:
+			dev->irq = nile4_to_irq(NILE4_INT_INTE);
+			break;
+		default:
+			break;
+		}
 	}
-    }
 }
 
 void __init pcibios_init(void)
 {
-    printk("PCI: Probing PCI hardware\n");
-    ioport_resource.end = 0x1ffffff;		/*  32 MB */
-    iomem_resource.end = 0x1fffffff;		/* 512 MB */
-    /* `ram' and `nile4' are requested through the Nile4 pci_dev */
-    request_resource(&iomem_resource, &ddb5074_resources.flash);
-    request_resource(&iomem_resource, &ddb5074_resources.isa_io);
-    request_resource(&iomem_resource, &ddb5074_resources.pci_io);
-    request_resource(&iomem_resource, &ddb5074_resources.isa_mem);
-    request_resource(&iomem_resource, &ddb5074_resources.pci_mem);
-    request_resource(&iomem_resource, &ddb5074_resources.boot);
-
-    pci_scan_bus(0, &nile4_pci_ops, NULL);
-    ddb5074_pci_fixup();
-    pci_assign_unassigned_resources();
-    pcibios_fixup_irqs();
+	printk("PCI: Probing PCI hardware\n");
+	ioport_resource.end = 0x1ffffff;	/*  32 MB */
+	iomem_resource.end = 0x1fffffff;	/* 512 MB */
+	/* `ram' and `nile4' are requested through the Nile4 pci_dev */
+	request_resource(&iomem_resource, &ddb5074_resources.flash);
+	request_resource(&iomem_resource, &ddb5074_resources.isa_io);
+	request_resource(&iomem_resource, &ddb5074_resources.pci_io);
+	request_resource(&iomem_resource, &ddb5074_resources.isa_mem);
+	request_resource(&iomem_resource, &ddb5074_resources.pci_mem);
+	request_resource(&iomem_resource, &ddb5074_resources.boot);
+
+	pci_scan_bus(0, &nile4_pci_ops, NULL);
+	ddb5074_pci_fixup();
+	pci_assign_unassigned_resources();
+	pcibios_fixup_irqs();
 }
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
-    bus->resource[1] = &ddb5074_resources.pci_mem;
+	bus->resource[1] = &ddb5074_resources.pci_mem;
 }
 
-char *pcibios_setup (char *str)
+char *pcibios_setup(char *str)
 {
-    return str;
+	return str;
 }
 
 void __init pcibios_update_irq(struct pci_dev *dev, int irq)
 {
-    pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
 void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus,
 				      struct pbus_set_ranges_data *ranges)
 {
-    ranges->io_start -= bus->resource[0]->start;
-    ranges->io_end -= bus->resource[0]->start;
-    ranges->mem_start -= bus->resource[1]->start;
-    ranges->mem_end -= bus->resource[1]->start;
+	ranges->io_start -= bus->resource[0]->start;
+	ranges->io_end -= bus->resource[0]->start;
+	ranges->mem_start -= bus->resource[1]->start;
+	ranges->mem_end -= bus->resource[1]->start;
 }
 
 int pcibios_enable_resources(struct pci_dev *dev)
@@ -323,15 +335,15 @@
 	 *  Don't touch the Nile 4
 	 */
 	if (dev->vendor == PCI_VENDOR_ID_NEC &&
-	    dev->device == PCI_DEVICE_ID_NEC_NILE4)
-	    return 0;
+	    dev->device == PCI_DEVICE_ID_NEC_NILE4) return 0;
 
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	old_cmd = cmd;
-	for(idx=0; idx<6; idx++) {
+	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);
+			printk(KERN_ERR "PCI: Device %s not available because "
+			       "of resource collisions\n", dev->slot_name);
 			return -EINVAL;
 		}
 		if (r->flags & IORESOURCE_IO)
@@ -340,7 +352,8 @@
 			cmd |= PCI_COMMAND_MEMORY;
 	}
 	if (cmd != old_cmd) {
-		printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, 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;
@@ -348,7 +361,7 @@
 
 int pcibios_enable_device(struct pci_dev *dev)
 {
-    return pcibios_enable_resources(dev);
+	return pcibios_enable_resources(dev);
 }
 
 void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
@@ -359,18 +372,23 @@
 
 	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
 	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4*resource;
+		reg = PCI_BASE_ADDRESS_0 + 4 * resource;
 	} else if (resource == PCI_ROM_RESOURCE) {
 		res->flags |= PCI_ROM_ADDRESS_ENABLE;
 		reg = dev->rom_base_reg;
 	} else {
-		/* Somebody might have asked allocation of a non-standard resource */
+		/*
+		 * 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)) {
+	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);
@@ -400,5 +418,4 @@
 }
 
 
-struct pci_fixup pcibios_fixups[] = {};
-
+struct pci_fixup pcibios_fixups[] = { };
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5074/prom.c linux/arch/mips/ddb5074/prom.c
--- v2.4.3/linux/arch/mips/ddb5074/prom.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/prom.c	Fri Apr 13 20:26:07 2001
@@ -3,58 +3,32 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: prom.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/bootmem.h>
+
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 
 
-char arcs_cmdline[CL_SIZE];
-
-extern char _end;
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x)	(((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
+char arcs_cmdline[COMMAND_LINE_SIZE];
 
 void __init prom_init(const char *s)
 {
-    int i = 0;
-    unsigned long mem_size, free_start, free_end, start_pfn, bootmap_size;
+	int i = 0;
 
-//  _serinit();
+	if (s != (void *) -1)
+		while (*s && i < sizeof(arcs_cmdline) - 1)
+			arcs_cmdline[i++] = *s++;
+	arcs_cmdline[i] = '\0';
 
-    if (s != (void *)-1)
-	while (*s && i < sizeof(arcs_cmdline)-1)
-	    arcs_cmdline[i++] = *s++;
-    arcs_cmdline[i] = '\0';
-
-    mips_machgroup = MACH_GROUP_NEC_DDB;
-    mips_machtype = MACH_NEC_DDB5074;
-    /* 64 MB non-upgradable */
-    mem_size = 64 << 20;
-
-    free_start = PHYSADDR(PFN_ALIGN(&_end));
-    free_end = mem_size;
-    start_pfn = PFN_UP((unsigned long)&_end);
-
-    /* Register all the contiguous memory with the bootmem allocator
-       and free it.  Be careful about the bootmem freemap.  */
-    bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT);
-
-    /* Free the entire available memory after the _end symbol.  */
-    free_start += bootmap_size;
-    free_bootmem(free_start, free_end-free_start);
-}
+	mips_machgroup = MACH_GROUP_NEC_DDB;
+	mips_machtype = MACH_NEC_DDB5074;
 
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
+	/* 64 MB non-upgradable */
+	add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
 }
 
 void __init prom_free_prom_memory(void)
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5074/setup.c linux/arch/mips/ddb5074/setup.c
--- v2.4.3/linux/arch/mips/ddb5074/setup.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/ddb5074/setup.c	Fri Apr 13 20:26:07 2001
@@ -3,10 +3,7 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: setup.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kbd_ll.h>
@@ -42,85 +39,83 @@
 extern struct ide_ops std_ide_ops;
 extern struct rtc_ops ddb_rtc_ops;
 
-static void (*back_to_prom)(void) = (void (*)(void))0xbfc00000;
+static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
 
 static void ddb_machine_restart(char *command)
 {
-    u32 t;
+	u32 t;
 
-    /* PCI cold reset */
-    t = nile4_in32(NILE4_PCICTRL+4);
-    t |= 0x40000000;
-    nile4_out32(NILE4_PCICTRL+4, t);
-    /* CPU cold reset */
-    t = nile4_in32(NILE4_CPUSTAT);
-    t |= 1;
-    nile4_out32(NILE4_CPUSTAT, t);
-    /* Call the PROM */
-    back_to_prom();
+	/* PCI cold reset */
+	t = nile4_in32(NILE4_PCICTRL + 4);
+	t |= 0x40000000;
+	nile4_out32(NILE4_PCICTRL + 4, t);
+	/* CPU cold reset */
+	t = nile4_in32(NILE4_CPUSTAT);
+	t |= 1;
+	nile4_out32(NILE4_CPUSTAT, t);
+	/* Call the PROM */
+	back_to_prom();
 }
 
 static void ddb_machine_halt(void)
 {
-    printk("DDB Vrc-5074 halted.\n");
-    do {} while (1);
+	printk("DDB Vrc-5074 halted.\n");
+	do {
+	} while (1);
 }
 
 static void ddb_machine_power_off(void)
 {
-    printk("DDB Vrc-5074 halted. Please turn off the power.\n");
-    do {} while (1);
+	printk("DDB Vrc-5074 halted. Please turn off the power.\n");
+	do {
+	} while (1);
 }
 
 extern void ddb_irq_setup(void);
 
-void (*board_time_init)(struct irqaction *irq);
+void (*board_time_init) (struct irqaction * irq);
 
 
 static void __init ddb_time_init(struct irqaction *irq)
 {
-    /* set the clock to 1 Hz */
-    nile4_out32(NILE4_T2CTRL, 1000000);
-    /* enable the General-Purpose Timer */
-    nile4_out32(NILE4_T2CTRL+4, 0x00000001);
-    /* reset timer */
-    nile4_out32(NILE4_T2CNTR, 0);
-    /* enable interrupt */
-    nile4_enable_irq(NILE4_INT_GPT);
-    i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
-    set_cp0_status(ST0_IM, IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+	/* set the clock to 1 Hz */
+	nile4_out32(NILE4_T2CTRL, 1000000);
+	/* enable the General-Purpose Timer */
+	nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
+	/* reset timer */
+	nile4_out32(NILE4_T2CNTR, 0);
+	/* enable interrupt */
+	nile4_enable_irq(NILE4_INT_GPT);
+	i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
+	change_cp0_status(ST0_IM,
+		          IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
 }
 
 void __init ddb_setup(void)
 {
-    extern int panic_timeout;
+	extern int panic_timeout;
 
-    irq_setup = ddb_irq_setup;
-    mips_io_port_base = NILE4_PCI_IO_BASE;
-    isa_slot_offset = NILE4_PCI_MEM_BASE;
-    request_region(0x00, 0x20, "dma1");
-    request_region(0x40, 0x20, "timer");
-    request_region(0x70, 0x10, "rtc");
-    request_region(0x80, 0x10, "dma page reg");
-    request_region(0xc0, 0x20, "dma2");
-    board_time_init = ddb_time_init;
-
-    _machine_restart = ddb_machine_restart;
-    _machine_halt = ddb_machine_halt;
-    _machine_power_off = ddb_machine_power_off;
+	irq_setup = ddb_irq_setup;
+	mips_io_port_base = NILE4_PCI_IO_BASE;
+	isa_slot_offset = NILE4_PCI_MEM_BASE;
+	request_region(0x00, 0x20, "dma1");
+	request_region(0x40, 0x20, "timer");
+	request_region(0x70, 0x10, "rtc");
+	request_region(0x80, 0x10, "dma page reg");
+	request_region(0xc0, 0x20, "dma2");
+	board_time_init = ddb_time_init;
+
+	_machine_restart = ddb_machine_restart;
+	_machine_halt = ddb_machine_halt;
+	_machine_power_off = ddb_machine_power_off;
 
 #ifdef CONFIG_BLK_DEV_IDE
-    ide_ops = &std_ide_ops;
+	ide_ops = &std_ide_ops;
 #endif
-    rtc_ops = &ddb_rtc_ops;
+	rtc_ops = &ddb_rtc_ops;
 
-    /* Reboot on panic */
-    panic_timeout = 180;
-}
-
-int __init page_is_ram(unsigned long pagenr)
-{
-    return 1;
+	/* Reboot on panic */
+	panic_timeout = 180;
 }
 
 
@@ -133,12 +128,12 @@
 #define NS16550_BASE		(NILE4_PCI_IO_BASE+0x03f8)
 static inline u8 ns16550_in(u32 reg)
 {
-    return *(volatile u8 *)(NS16550_BASE+reg);
+	return *(volatile u8 *) (NS16550_BASE + reg);
 }
 
 static inline void ns16550_out(u32 reg, u8 val)
 {
-    *(volatile u8 *)(NS16550_BASE+reg) = val;
+	*(volatile u8 *) (NS16550_BASE + reg) = val;
 }
 #endif
 
@@ -168,87 +163,84 @@
 void _serinit(void)
 {
 #if USE_NILE4_SERIAL
-    ns16550_out(NS16550_LCR, 0x80);
-    ns16550_out(NS16550_DLM, 0x00);
-    ns16550_out(NS16550_DLL, 0x36);	/* 9600 baud */
-    ns16550_out(NS16550_LCR, 0x00);
-    ns16550_out(NS16550_LCR, 0x03);
-    ns16550_out(NS16550_FCR, 0x47);
+	ns16550_out(NS16550_LCR, 0x80);
+	ns16550_out(NS16550_DLM, 0x00);
+	ns16550_out(NS16550_DLL, 0x36);	/* 9600 baud */
+	ns16550_out(NS16550_LCR, 0x00);
+	ns16550_out(NS16550_LCR, 0x03);
+	ns16550_out(NS16550_FCR, 0x47);
 #else
-    /* done by PMON */
+	/* done by PMON */
 #endif
 }
 
 void _putc(char c)
 {
-    while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-    ns16550_out(NS16550_THR, c);
-    if (c == '\n') {
 	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-	ns16550_out(NS16550_THR, '\r');
-    }
+	ns16550_out(NS16550_THR, c);
+	if (c == '\n') {
+		while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+		ns16550_out(NS16550_THR, '\r');
+	}
 }
 
 void _puts(const char *s)
 {
-    char c;
-    while ((c = *s++))
-	_putc(c);
+	char c;
+	while ((c = *s++))
+		_putc(c);
 }
 
 char _getc(void)
 {
-    while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
-    return ns16550_in(NS16550_RBR);
+	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
+	return ns16550_in(NS16550_RBR);
 }
 
 int _testc(void)
 {
-    return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
+	return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
 }
 
 
-    /*
-     *  Hexadecimal 7-segment LED
-     */
-
+/*
+ *  Hexadecimal 7-segment LED
+ */
 void ddb5074_led_hex(int hex)
 {
-    outb(hex, 0x80);
+	outb(hex, 0x80);
 }
 
 
-    /*
-     *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
-     */
-
+/*
+ *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
+ */
 struct pci_dev *pci_pmu = NULL;
 
 void ddb5074_led_d2(int on)
 {
-    u8 t;
+	u8 t;
 
-    if (pci_pmu) {
-	pci_read_config_byte(pci_pmu, 0x7e, &t);
-	if (on)
-	    t &= 0x7f;
-	else
-	    t |= 0x80;
-	pci_write_config_byte(pci_pmu, 0x7e, t);
-    }
+	if (pci_pmu) {
+		pci_read_config_byte(pci_pmu, 0x7e, &t);
+		if (on)
+			t &= 0x7f;
+		else
+			t |= 0x80;
+		pci_write_config_byte(pci_pmu, 0x7e, t);
+	}
 }
 
 void ddb5074_led_d3(int on)
 {
-    u8 t;
+	u8 t;
 
-    if (pci_pmu) {
-	pci_read_config_byte(pci_pmu, 0x7e, &t);
-	if (on)
-	    t &= 0xbf;
-	else
-	    t |= 0x40;
-	pci_write_config_byte(pci_pmu, 0x7e, t);
-    }
+	if (pci_pmu) {
+		pci_read_config_byte(pci_pmu, 0x7e, &t);
+		if (on)
+			t &= 0xbf;
+		else
+			t |= 0x40;
+		pci_write_config_byte(pci_pmu, 0x7e, t);
+	}
 }
-
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5074/time.c linux/arch/mips/ddb5074/time.c
--- v2.4.3/linux/arch/mips/ddb5074/time.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/time.c	Fri Apr 13 20:26:07 2001
@@ -3,33 +3,30 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id*
  */
-
 #include <linux/init.h>
 #include <asm/mc146818rtc.h>
 
 static unsigned char ddb_rtc_read_data(unsigned long addr)
 {
-    outb_p(addr, RTC_PORT(0));
-    return inb_p(RTC_PORT(1));
+	outb_p(addr, RTC_PORT(0));
+
+	return inb_p(RTC_PORT(1));
 }
 
 static void ddb_rtc_write_data(unsigned char data, unsigned long addr)
 {
-    outb_p(addr, RTC_PORT(0));
-    outb_p(data, RTC_PORT(1));
+	outb_p(addr, RTC_PORT(0));
+	outb_p(data, RTC_PORT(1));
 }
 
 static int ddb_rtc_bcd_mode(void)
 {
-    return 1;
+	return 1;
 }
 
 struct rtc_ops ddb_rtc_ops = {
-    ddb_rtc_read_data,
-    ddb_rtc_write_data,
-    ddb_rtc_bcd_mode
+	ddb_rtc_read_data,
+	ddb_rtc_write_data,
+	ddb_rtc_bcd_mode
 };
-
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5476/Makefile linux/arch/mips/ddb5476/Makefile
--- v2.4.3/linux/arch/mips/ddb5476/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/Makefile	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,23 @@
+#
+# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+O_TARGET = ddb5476.a
+
+obj-y				+= setup.o irq.o time.o prom.o pci.o \
+				   int-handler.o nile4.o
+obj-$(CONFIG_REMOTE_DEBUG)	+= dbg_io.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5476/dbg_io.c linux/arch/mips/ddb5476/dbg_io.c
--- v2.4.3/linux/arch/mips/ddb5476/dbg_io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/dbg_io.c	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,125 @@
+
+#include <linux/config.h>
+
+#if (defined(CONFIG_DDB5476) && defined(CONFIG_REMOTE_DEBUG))
+
+/* --- CONFIG --- */
+
+/* we need uint32 uint8 */
+/* #include "types.h" */
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+/* --- END OF CONFIG --- */
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [jsun] we use the second serial port for kdb */
+#define         BASE                    0xa60002f8
+#define         MAX_BAUD                115200
+
+/* === END OF CONFIG === */
+
+/* register offset */
+#define         OFS_RCV_BUFFER          0
+#define         OFS_TRANS_HOLD          0
+#define         OFS_SEND_BUFFER         0
+#define         OFS_INTR_ENABLE         1
+#define         OFS_INTR_ID             2
+#define         OFS_DATA_FORMAT         3
+#define         OFS_LINE_CONTROL        3
+#define         OFS_MODEM_CONTROL       4
+#define         OFS_RS232_OUTPUT        4
+#define         OFS_LINE_STATUS         5
+#define         OFS_MODEM_STATUS        6
+#define         OFS_RS232_INPUT         6
+#define         OFS_SCRATCH_PAD         7
+
+#define         OFS_DIVISOR_LSB         0
+#define         OFS_DIVISOR_MSB         1
+
+
+/* memory-mapped read/write of the port */
+#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
+#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+	/* disable interrupts */
+	UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+	/* set up buad rate */
+	{
+		uint32 divisor;
+
+		/* set DIAB bit */
+		UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+		/* set divisor */
+		divisor = MAX_BAUD / baud;
+		UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+		UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+		/* clear DIAB bit */
+		UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+	}
+
+	/* set data format */
+	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_38400,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+	return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_9600,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+	UART16550_WRITE(OFS_SEND_BUFFER, byte);
+	return 1;
+}
+
+#endif
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5476/int-handler.S linux/arch/mips/ddb5476/int-handler.S
--- v2.4.3/linux/arch/mips/ddb5476/int-handler.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/int-handler.S	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,125 @@
+/*
+ *  arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
+ *
+ *  Based on arch/mips/sgi/kernel/indyIRQ.S
+ *
+ *  Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the INDY look basically (barring software IRQs
+ * which we don't use at all) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Local IRQ level zero
+ *             3        Local IRQ level one
+ *             4        8254 Timer zero
+ *             5        8254 Timer one
+ *             6        Bus Error
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ *                  Local IRQ zero
+ *                  Local IRQ one
+ *                  Bus Error
+ *                  8254 Timer zero
+ * Lowest  ----     8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+	.text
+	.set	noreorder
+	.set	noat
+	.align	5
+	NESTED(ddbIRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+	.set	at
+	mfc0	s1, CP0_CAUSE		# get irq mask
+
+#if 1
+	mfc0	t2,CP0_STATUS		# get enabled interrupts
+	and	s0, s1, t2		# isolate allowed ones
+#endif
+	/* First we check for r4k counter/timer IRQ. */
+	andi	a0, s0, CAUSEF_IP2	# delay slot, check local level zero
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP3	# delay slot, check local level one
+
+	/* Wheee, local level zero interrupt. */
+	jal	ddb_local0_irqdispatch
+	 move	a0, sp			# delay slot
+
+	j	ret_from_irq
+	 nop				# delay slot
+
+1:
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP6	# delay slot, check bus error
+
+	/* Wheee, local level one interrupt. */
+	move	a0, sp
+	jal	ddb_local1_irqdispatch
+	 nop
+
+	j	ret_from_irq
+	 nop
+
+1:
+	beq	a0, zero, 1f
+	 nop
+
+	/* Wheee, an asynchronous bus error... */
+	move	a0, sp
+	jal	ddb_buserror_irq
+	 nop
+
+	j	ret_from_irq
+	 nop
+
+1:
+	/* Here by mistake?  This is possible, what can happen
+	 * is that by the time we take the exception the IRQ
+	 * pin goes low, so just leave if this is the case.
+	 */
+	andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
+	beq	a0, zero, 1f
+
+	/* Must be one of the 8254 timers... */
+	move	a0, sp
+	jal	ddb_8254timer_irq
+	 nop
+1:
+	/* phamtom interrupt */
+	move 	a0, s1
+	jal	ddb_phantom_irq
+	nop
+	j	ret_from_irq
+	nop
+	END(ddbIRQ)
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5476/irq.c linux/arch/mips/ddb5476/irq.c
--- v2.4.3/linux/arch/mips/ddb5476/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/irq.c	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,251 @@
+/*
+ *  arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/nile4.h>
+
+extern void __init i8259_init(void);
+extern void i8259_disable_irq(unsigned int irq_nr);
+extern void i8259_enable_irq(unsigned int irq_nr);
+
+extern asmlinkage void ddbIRQ(void);
+extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs);
+extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+
+
+void no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+}
+
+
+#define M1543_PNP_CONFIG	0x03f0	/* PnP Config Port */
+#define M1543_PNP_INDEX		0x03f0	/* PnP Index Port */
+#define M1543_PNP_DATA		0x03f1	/* PnP Data Port */
+
+#define M1543_PNP_ALT_CONFIG	0x0370	/* Alternative PnP Config Port */
+#define M1543_PNP_ALT_INDEX	0x0370	/* Alternative PnP Index Port */
+#define M1543_PNP_ALT_DATA	0x0371	/* Alternative PnP Data Port */
+
+#define M1543_INT1_MASTER_CTRL	0x0020	/* INT_1 (master) Control Register */
+#define M1543_INT1_MASTER_MASK	0x0021	/* INT_1 (master) Mask Register */
+
+#define M1543_INT1_SLAVE_CTRL	0x00a0	/* INT_1 (slave) Control Register */
+#define M1543_INT1_SLAVE_MASK	0x00a1	/* INT_1 (slave) Mask Register */
+
+#define M1543_INT1_MASTER_ELCR	0x04d0	/* INT_1 (master) Edge/Level Control */
+#define M1543_INT1_SLAVE_ELCR	0x04d1	/* INT_1 (slave) Edge/Level Control */
+
+static struct {
+	struct resource m1543_config;
+	struct resource pic_elcr;
+} m1543_ioport = {
+	{ "M1543 config", M1543_PNP_CONFIG, M1543_PNP_CONFIG + 1,
+	  IORESOURCE_BUSY},
+	{ "pic ELCR", M1543_INT1_MASTER_ELCR, M1543_INT1_MASTER_ELCR + 1,
+	  IORESOURCE_BUSY}
+};
+
+static void m1543_irq_setup(void)
+{
+	/*
+	 *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
+	 *  the possible IO sources in the M1543 are in use by us.  We will
+	 *  use the following mapping:
+	 *
+	 *      IRQ1  - keyboard (default set by M1543)
+	 *      IRQ3  - reserved for UART B (default set by M1543) (note that
+	 *              the schematics for the DDB Vrc-5476 board seem to 
+	 *              indicate that IRQ3 is connected to the DS1386 
+	 *              watchdog timer interrupt output so we might have 
+	 *              a conflict)
+	 *      IRQ4  - reserved for UART A (default set by M1543)
+	 *      IRQ5  - parallel (default set by M1543)
+	 *      IRQ8  - DS1386 time of day (RTC) interrupt
+	 *      IRQ9  - USB (hardwired in ddb_setup)
+	 *      IRQ10 - PMU (hardwired in ddb_setup)
+	 *      IRQ12 - mouse
+	 *      IRQ14,15 - IDE controller (need to be confirmed, jsun)
+	 */
+
+	/*
+	 *  Assing mouse interrupt to IRQ12 
+	 */
+
+	/* Enter configuration mode */
+	outb(0x51, M1543_PNP_CONFIG);
+	outb(0x23, M1543_PNP_CONFIG);
+
+	/* Select logical device 7 (Keyboard) */
+	outb(0x07, M1543_PNP_INDEX);
+	outb(0x07, M1543_PNP_DATA);
+
+	/* Select IRQ12 */
+	outb(0x72, M1543_PNP_INDEX);
+	outb(0x0c, M1543_PNP_DATA);
+
+	/* Leave configration mode */
+	outb(0xbb, M1543_PNP_CONFIG);
+
+
+	/* Initialize the 8259 PIC in the M1543 */
+	i8259_init();
+
+	/* Enable the interrupt cascade from M1543 */
+	nile4_enable_irq(NILE4_INT_INTC);
+
+	/* request io ports */
+	if (request_resource(&ioport_resource, &m1543_ioport.m1543_config)
+	    || request_resource(&ioport_resource, &m1543_ioport.pic_elcr)) {
+		printk("m1543_irq_setup : requesting io ports failed.\n");
+		for (;;);
+	}
+}
+
+static void nile4_irq_setup(void)
+{
+	int i;
+
+	/* Map all interrupts to CPU int #0 */
+	nile4_map_irq_all(0);
+
+	/* PCI INTA#-E# must be level triggered */
+	nile4_set_pci_irq_level_or_edge(0, 1);
+	nile4_set_pci_irq_level_or_edge(1, 1);
+	nile4_set_pci_irq_level_or_edge(2, 1);
+	nile4_set_pci_irq_level_or_edge(3, 1);
+
+	/* PCI INTA#, B#, D# must be active low, INTC# must be active high */
+	nile4_set_pci_irq_polarity(0, 0);
+	nile4_set_pci_irq_polarity(1, 0);
+	nile4_set_pci_irq_polarity(2, 1);
+	nile4_set_pci_irq_polarity(3, 0);
+
+	for (i = 0; i < 16; i++)
+		nile4_clear_irq(i);
+
+	/* Enable CPU int #0 */
+	nile4_enable_irq_output(0);
+
+	/* memory resource acquire in ddb_setup */
+}
+
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
+
+
+void disable_irq(unsigned int irq_nr)
+{
+	if (is_i8259_irq(irq_nr))
+		i8259_disable_irq(irq_nr);
+	else
+		nile4_disable_irq(irq_to_nile4(irq_nr));
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+	if (is_i8259_irq(irq_nr))
+		i8259_enable_irq(irq_nr);
+	else
+		nile4_enable_irq(irq_to_nile4(irq_nr));
+}
+
+int table[16] = { 0, };
+
+void ddb_local0_irqdispatch(struct pt_regs *regs)
+{
+	u32 mask;
+	int nile4_irq;
+#if 0
+	volatile static int nesting = 0;
+	if (nesting++ == 0)
+		ddb5476_led_d3(1);
+	ddb5476_led_hex(nesting < 16 ? nesting : 15);
+#endif
+
+	mask = nile4_get_irq_stat(0);
+	nile4_clear_irq_mask(mask);
+
+	/* Handle the timer interrupt first */
+	if (mask & (1 << NILE4_INT_GPT)) {
+		nile4_disable_irq(NILE4_INT_GPT);
+		do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
+		nile4_enable_irq(NILE4_INT_GPT);
+		mask &= ~(1 << NILE4_INT_GPT);
+	}
+	for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
+		if (mask & 1) {
+			nile4_disable_irq(nile4_irq);
+			if (nile4_irq == NILE4_INT_INTC) {
+				int i8259_irq = nile4_i8259_iack();
+				i8259_do_irq(i8259_irq, regs);
+			} else {
+				do_IRQ(nile4_to_irq(nile4_irq), regs);
+			}
+			nile4_enable_irq(nile4_irq);
+		}
+#if 0
+	if (--nesting == 0)
+		ddb5476_led_d3(0);
+	ddb5476_led_hex(nesting < 16 ? nesting : 15);
+#endif
+}
+
+void ddb_local1_irqdispatch(void)
+{
+	printk("ddb_local1_irqdispatch called\n");
+}
+
+void ddb_buserror_irq(void)
+{
+	printk("ddb_buserror_irq called\n");
+}
+
+void ddb_8254timer_irq(void)
+{
+	printk("ddb_8254timer_irq called\n");
+}
+
+void ddb_phantom_irq(unsigned long cause)
+{
+	printk("phantom interrupts detected : \n");
+	printk("\tcause \t\t0x%08x\n", cause);
+	printk("\tcause reg\t0x%08x\n",
+	       read_32bit_cp0_register(CP0_CAUSE));
+	printk("\tstatus reg\t0x%08x\n",
+	       read_32bit_cp0_register(CP0_STATUS));
+}
+
+void __init ddb_irq_setup(void)
+{
+#ifdef CONFIG_REMOTE_DEBUG
+	printk("Wait for gdb client connection ...\n");
+	set_debug_traps();
+	breakpoint();		/* you may move this line to whereever you want :-) */
+#endif
+	i8259_setup_irq(2, &irq2);
+
+	nile4_irq_setup();
+	m1543_irq_setup();
+
+	/* we pin #0 - #4 (no internal timer) */
+	change_cp0_status(ST0_IM,
+	                  IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+
+	set_except_vector(0, ddbIRQ);
+}
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5476/nile4.c linux/arch/mips/ddb5476/nile4.c
--- v2.4.3/linux/arch/mips/ddb5476/nile4.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/nile4.c	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,293 @@
+/*
+ *  arch/mips/ddb5074/nile4.c -- NEC Vrc-5074 Nile 4 support routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/nile4.h>
+
+
+/*
+ *  Physical Device Address Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
+void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
+		    int on_memory_bus, int visible)
+{
+	u32 maskbits;
+	u32 widthbits;
+
+	if (pdar > NILE4_BOOTCS || (pdar & 7)) {
+		printk("nile4_set_pdar: invalid pdar %d\n", pdar);
+		return;
+	}
+	if (pdar == NILE4_INTCS && size != 0x00200000) {
+		printk("nile4_set_pdar: INTCS size must be 2 MB\n");
+		return;
+	}
+	switch (size) {
+#if 0				/* We don't support 4 GB yet */
+	case 0x100000000:	/* 4 GB */
+		maskbits = 4;
+		break;
+#endif
+	case 0x80000000:	/* 2 GB */
+		maskbits = 5;
+		break;
+	case 0x40000000:	/* 1 GB */
+		maskbits = 6;
+		break;
+	case 0x20000000:	/* 512 MB */
+		maskbits = 7;
+		break;
+	case 0x10000000:	/* 256 MB */
+		maskbits = 8;
+		break;
+	case 0x08000000:	/* 128 MB */
+		maskbits = 9;
+		break;
+	case 0x04000000:	/* 64 MB */
+		maskbits = 10;
+		break;
+	case 0x02000000:	/* 32 MB */
+		maskbits = 11;
+		break;
+	case 0x01000000:	/* 16 MB */
+		maskbits = 12;
+		break;
+	case 0x00800000:	/* 8 MB */
+		maskbits = 13;
+		break;
+	case 0x00400000:	/* 4 MB */
+		maskbits = 14;
+		break;
+	case 0x00200000:	/* 2 MB */
+		maskbits = 15;
+		break;
+	case 0:		/* OFF */
+		maskbits = 0;
+		break;
+	default:
+		printk("nile4_set_pdar: unsupported size %p\n",
+		       (void *) size);
+		return;
+	}
+	switch (width) {
+	case 8:
+		widthbits = 0;
+		break;
+	case 16:
+		widthbits = 1;
+		break;
+	case 32:
+		widthbits = 2;
+		break;
+	case 64:
+		widthbits = 3;
+		break;
+	default:
+		printk("nile4_set_pdar: unsupported width %d\n", width);
+		return;
+	}
+	nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
+		    (visible ? 0x20 : 0) | (widthbits << 6) |
+		    (phys & 0xffe00000));
+	nile4_out32(pdar + 4, 0);
+	/*
+	 * When programming a PDAR, the register should be read immediately
+	 * after writing it. This ensures that address decoders are properly
+	 * configured.
+	 */
+	nile4_in32(pdar);
+	nile4_in32(pdar + 4);
+}
+
+
+/*
+ *  PCI Master Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
+void nile4_set_pmr(u32 pmr, u32 type, u32 addr)
+{
+	if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
+		printk("nile4_set_pmr: invalid pmr %d\n", pmr);
+		return;
+	}
+	switch (type) {
+	case NILE4_PCICMD_IACK:	/* PCI Interrupt Acknowledge */
+	case NILE4_PCICMD_IO:	/* PCI I/O Space */
+	case NILE4_PCICMD_MEM:	/* PCI Memory Space */
+	case NILE4_PCICMD_CFG:	/* PCI Configuration Space */
+		break;
+	default:
+		printk("nile4_set_pmr: invalid type %d\n", type);
+		return;
+	}
+	nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
+	nile4_out32(pmr + 4, 0);
+}
+
+
+/*
+ *  Interrupt Programming
+ */
+void nile4_map_irq(int nile4_irq, int cpu_irq)
+{
+	u32 offset, t;
+
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t &= ~(7 << (nile4_irq * 4));
+	t |= cpu_irq << (nile4_irq * 4);
+	nile4_out32(offset, t);
+}
+
+void nile4_map_irq_all(int cpu_irq)
+{
+	u32 all, t;
+
+	all = cpu_irq;
+	all |= all << 4;
+	all |= all << 8;
+	all |= all << 16;
+	t = nile4_in32(NILE4_INTCTRL);
+	t &= 0x88888888;
+	t |= all;
+	nile4_out32(NILE4_INTCTRL, t);
+	t = nile4_in32(NILE4_INTCTRL + 4);
+	t &= 0x88888888;
+	t |= all;
+	nile4_out32(NILE4_INTCTRL + 4, t);
+}
+
+void nile4_enable_irq(int nile4_irq)
+{
+	u32 offset, t;
+
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t |= 8 << (nile4_irq * 4);
+	nile4_out32(offset, t);
+}
+
+void nile4_disable_irq(int nile4_irq)
+{
+	u32 offset, t;
+
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t &= ~(8 << (nile4_irq * 4));
+	nile4_out32(offset, t);
+}
+
+void nile4_disable_irq_all(void)
+{
+	nile4_out32(NILE4_INTCTRL, 0);
+	nile4_out32(NILE4_INTCTRL + 4, 0);
+}
+
+u16 nile4_get_irq_stat(int cpu_irq)
+{
+	return nile4_in16(NILE4_INTSTAT0 + cpu_irq * 2);
+}
+
+void nile4_enable_irq_output(int cpu_irq)
+{
+	u32 t;
+
+	t = nile4_in32(NILE4_INTSTAT1 + 4);
+	t |= 1 << (16 + cpu_irq);
+	nile4_out32(NILE4_INTSTAT1, t);
+}
+
+void nile4_disable_irq_output(int cpu_irq)
+{
+	u32 t;
+
+	t = nile4_in32(NILE4_INTSTAT1 + 4);
+	t &= ~(1 << (16 + cpu_irq));
+	nile4_out32(NILE4_INTSTAT1, t);
+}
+
+void nile4_set_pci_irq_polarity(int pci_irq, int high)
+{
+	u32 t;
+
+	t = nile4_in32(NILE4_INTPPES);
+	if (high)
+		t &= ~(1 << (pci_irq * 2));
+	else
+		t |= 1 << (pci_irq * 2);
+	nile4_out32(NILE4_INTPPES, t);
+}
+
+void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
+{
+	u32 t;
+
+	t = nile4_in32(NILE4_INTPPES);
+	if (level)
+		t |= 2 << (pci_irq * 2);
+	else
+		t &= ~(2 << (pci_irq * 2));
+	nile4_out32(NILE4_INTPPES, t);
+}
+
+void nile4_clear_irq(int nile4_irq)
+{
+	nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
+}
+
+void nile4_clear_irq_mask(u32 mask)
+{
+	nile4_out32(NILE4_INTCLR, mask);
+}
+
+u8 nile4_i8259_iack(void)
+{
+	u8 irq;
+
+	/* Set window 0 for interrupt acknowledge */
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
+	irq = *(volatile u8 *) NILE4_PCI_IACK_BASE;
+	/* Set window 0 for PCI I/O space */
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
+	return irq;
+}
+
+#if 0
+void nile4_dump_irq_status(void)
+{
+	printk("CPUSTAT = %p:%p\n", (void *) nile4_in32(NILE4_CPUSTAT + 4),
+	       (void *) nile4_in32(NILE4_CPUSTAT));
+	printk("INTCTRL = %p:%p\n", (void *) nile4_in32(NILE4_INTCTRL + 4),
+	       (void *) nile4_in32(NILE4_INTCTRL));
+	printk("INTSTAT0 = %p:%p\n",
+	       (void *) nile4_in32(NILE4_INTSTAT0 + 4),
+	       (void *) nile4_in32(NILE4_INTSTAT0));
+	printk("INTSTAT1 = %p:%p\n",
+	       (void *) nile4_in32(NILE4_INTSTAT1 + 4),
+	       (void *) nile4_in32(NILE4_INTSTAT1));
+	printk("INTCLR = %p:%p\n", (void *) nile4_in32(NILE4_INTCLR + 4),
+	       (void *) nile4_in32(NILE4_INTCLR));
+	printk("INTPPES = %p:%p\n", (void *) nile4_in32(NILE4_INTPPES + 4),
+	       (void *) nile4_in32(NILE4_INTPPES));
+}
+#endif
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5476/pci.c linux/arch/mips/ddb5476/pci.c
--- v2.4.3/linux/arch/mips/ddb5476/pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/pci.c	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,495 @@
+/*
+ *  arch/mips/ddb5476/pci.c -- NEC DDB Vrc-5074 PCI access routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Albert Dorofeev <albert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+
+#include <asm-mips/nile4.h>
+
+
+static u32 nile4_pre_pci_access0(int slot_num)
+{
+	u32 pci_addr = 0;
+	u32 virt_addr = NILE4_PCI_CFG_BASE;
+
+	/* work around the bug for Vrc5476 */
+	if (slot_num == 13)
+		return NILE4_BASE + NILE4_PCI_BASE;
+
+	/* Set window 1 address 08000000 - 32 bit - 128 MB (PCI config space) */
+	nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x08000000, 32, 0,
+		       0);
+
+	// [jsun] we start scanning from addr:10, 
+	// with 128M we can go up to addr:26 (slot 16)
+	if (slot_num <= 16) {
+		virt_addr += 0x00000400 << slot_num;
+	} else {
+		/* for high slot, we have to set higher PCI base addr */
+		pci_addr = 0x00000400 << slot_num;
+	}
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr);
+	return virt_addr;
+}
+
+static void nile4_post_pci_access0(void)
+{
+	/*
+	 * Set window 1 back to address 08000000 - 32 bit - 128 MB
+	 * (PCI IO space)
+	 */
+	nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE),
+		       0x08000000, 32, 1, 1);
+	// nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0x08000000);
+}
+
+
+static int nile4_pci_read_config_dword(struct pci_dev *dev,
+				       int where, u32 * val)
+{
+	int slot_num, func_num;
+	u32 base;
+	u32 addr;
+
+	/*
+	 *  Do we need to generate type 1 configure transaction?
+	 */
+	if (dev->bus->number) {
+		/* FIXME - not working yet */
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+		/*
+		 * the largest type 1 configuration addr is 16M, < 256M
+		 * config space
+		 */
+		slot_num = 0;
+		addr =
+		    (dev->bus->number << 16) | (dev->devfn <
+						8) | where | 1;
+	} else {
+		slot_num = PCI_SLOT(dev->devfn);
+		func_num = PCI_FUNC(dev->devfn);
+		addr = (func_num << 8) + where;
+	}
+
+	base = nile4_pre_pci_access0(slot_num);
+	*val = *(volatile u32 *) (base + addr);
+	nile4_post_pci_access0();
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_write_config_dword(struct pci_dev *dev, int where,
+					u32 val)
+{
+	int slot_num, func_num;
+	u32 base;
+	u32 addr;
+
+	/*
+	 *  Do we need to generate type 1 configure transaction?
+	 */
+	if (dev->bus->number) {
+		/* FIXME - not working yet */
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+		/* the largest type 1 configuration addr is 16M, < 256M config space */
+		slot_num = 0;
+		addr =
+		    (dev->bus->number << 16) | (dev->devfn <
+						8) | where | 1;
+	} else {
+		slot_num = PCI_SLOT(dev->devfn);
+		func_num = PCI_FUNC(dev->devfn);
+		addr = (func_num << 8) + where;
+	}
+
+	base = nile4_pre_pci_access0(slot_num);
+	*(volatile u32 *) (base + addr) = val;
+	nile4_post_pci_access0();
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_read_config_word(struct pci_dev *dev, int where,
+				      u16 * val)
+{
+	int status;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xffff;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_read_config_byte(struct pci_dev *dev, int where,
+				      u8 * val)
+{
+	int status;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 1)
+		result >>= 8;
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xff;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_write_config_word(struct pci_dev *dev, int where,
+				       u16 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		shift += 16;
+	result &= ~(0xffff << shift);
+	result |= val << shift;
+	return nile4_pci_write_config_dword(dev, where & ~3, result);
+}
+
+static int nile4_pci_write_config_byte(struct pci_dev *dev, int where,
+				       u8 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		shift += 16;
+	if (where & 1)
+		shift += 8;
+	result &= ~(0xff << shift);
+	result |= val << shift;
+	return nile4_pci_write_config_dword(dev, where & ~3, result);
+}
+
+struct pci_ops nile4_pci_ops = {
+	nile4_pci_read_config_byte,
+	nile4_pci_read_config_word,
+	nile4_pci_read_config_dword,
+	nile4_pci_write_config_byte,
+	nile4_pci_write_config_word,
+	nile4_pci_write_config_dword
+};
+
+struct {
+	struct resource ram;
+	struct resource flash;
+	struct resource isa_io;
+	struct resource pci_io;
+	struct resource isa_mem;
+	struct resource pci_mem;
+	struct resource nile4;
+	struct resource boot;
+} ddb5476_resources = {
+	// { "RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
+	{
+	"RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM}, {
+	"Flash ROM", 0x04000000, 0x043fffff}, {
+	"Nile4 ISA I/O", 0x06000000, 0x060fffff}, {
+	"Nile4 PCI I/O", 0x06100000, 0x07ffffff}, {
+	"Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM}, {
+	"Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM},
+	    // { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
+	{
+	"Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM}, {
+	"Boot ROM", 0x1fc00000, 0x1fffffff}
+};
+
+struct resource M5229_resources[5] = {
+	{"M5229 BAR0", 0x1f0, 0x1f3, IORESOURCE_IO},
+	{"M5229 BAR1", 0x3f4, 0x3f7, IORESOURCE_IO},
+	{"M5229 BAR2", 0x170, 0x173, IORESOURCE_IO},
+	{"M5229 BAR3", 0x374, 0x377, IORESOURCE_IO},
+	{"M5229 BAR4", 0xf000, 0xf00f, IORESOURCE_IO}
+};
+
+static void __init ddb5476_pci_fixup(void)
+{
+	struct pci_dev *dev;
+
+	pci_for_each_dev(dev) {
+		if (dev->vendor == PCI_VENDOR_ID_NEC &&
+		    dev->device == PCI_DEVICE_ID_NEC_VRC5476) {
+			/*
+			 * The first 64-bit PCI base register should point to
+			 * the Nile4 control registers. Unfortunately this
+			 * isn't the case, so we fix it ourselves. This allows
+			 * the serial driver to find the UART.
+			 */
+			dev->resource[0] = ddb5476_resources.nile4;
+			request_resource(&iomem_resource,
+					 &dev->resource[0]);
+			/*
+			 * The second 64-bit PCI base register points to the
+			 * first memory bank. Unfortunately the address is
+			 * wrong, so we fix it (again).
+			 */
+
+			/* [jsun] We cannot request the resource anymore,
+			 * because kernel/setup.c has already reserved "System 
+			 * RAM" resource at the same spot.  
+			 * The fundamental problem here is that PCI host 
+			 * controller should not put system RAM mapping in BAR
+			 * and make subject to PCI resource assignement.
+			 * Current fix is a total hack.  We set parent to 1 so
+                         * so that PCI resource assignement code is fooled to 
+                         * think the resource is assigned, and will not attempt
+                         * to mess with it.
+			 */
+			dev->resource[2] = ddb5476_resources.ram;
+			if (request_resource(&iomem_resource,
+			                     &dev->resource[2]) ) {
+				dev->resource[2].parent = 0x1;
+                        }
+
+		} else if (dev->vendor == PCI_VENDOR_ID_AL
+			   && dev->device == PCI_DEVICE_ID_AL_M7101) {
+			/*
+			 * It's nice to have the LEDs on the GPIO pins
+			 * available for debugging
+			 */
+			extern struct pci_dev *pci_pmu;
+			u8 t8;
+
+			pci_pmu = dev;	/* for LEDs D2 and D3 */
+			/* Program the lines for LEDs D2 and D3 to output */
+			nile4_pci_read_config_byte(dev, 0x7d, &t8);
+			t8 |= 0xc0;
+			nile4_pci_write_config_byte(dev, 0x7d, t8);
+			/* Turn LEDs D2 and D3 off */
+			nile4_pci_read_config_byte(dev, 0x7e, &t8);
+			t8 |= 0xc0;
+			nile4_pci_write_config_byte(dev, 0x7e, t8);
+		} else if (dev->vendor == PCI_VENDOR_ID_AL &&
+			   dev->device == 0x5229) {
+			int i;
+			for (i = 0; i < 5; i++) {
+				dev->resource[i] = M5229_resources[i];
+				request_resource(&ioport_resource,
+						 &dev->resource[i]);
+			}
+		}
+	}
+}
+
+static void __init pcibios_fixup_irqs(void)
+{
+	struct pci_dev *dev;
+	int slot_num;
+
+	pci_for_each_dev(dev) {
+		slot_num = PCI_SLOT(dev->devfn);
+		switch (slot_num) {
+		case 3:	/* re-programmed to USB */
+			dev->irq = 9;	/* hard-coded; see irq.c */
+			break;
+		case 4:	/* re-programmed to PMU */
+			dev->irq = 10;	/* hard-coded; see irq.c */
+			break;
+		case 6:	/* on-board pci-pci bridge */
+			dev->irq = 0xff;
+			break;
+		case 7:	/* on-board ether */
+			dev->irq = nile4_to_irq(NILE4_INT_INTB);
+			break;
+		case 8:	/* ISA-PCI bridge  */
+			dev->irq = nile4_to_irq(NILE4_INT_INTC);
+			break;
+		case 9:	/* ext slot #3 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTD);
+			break;
+		case 10:	/* ext slot #4 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTA);
+			break;
+		case 13:	/* Vrc5476 */
+			dev->irq = 0xff;
+			break;
+		case 14:	/* HD controller, M5229 */
+			dev->irq = 14;
+			break;
+		default:
+			printk
+			    ("JSUN : in pcibios_fixup_irqs - unkown slot %d\n",
+			     slot_num);
+			panic
+			    ("JSUN : in pcibios_fixup_irqs - unkown slot.\n");
+		}
+	}
+}
+
+void __init pcibios_init(void)
+{
+	printk("PCI: Emulate bios initialization \n");
+	/* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
+	*(long *) (NILE4_BASE + NILE4_BAR0) = 0x8;
+
+	printk("PCI: Probing PCI hardware\n");
+	ioport_resource.end = 0x1ffffff;	/*  32 MB */
+	iomem_resource.end = 0x1fffffff;	/* 512 MB */
+
+	/* `ram' and `nile4' are requested through the Nile4 pci_dev */
+	request_resource(&iomem_resource, &ddb5476_resources.flash);
+	request_resource(&iomem_resource, &ddb5476_resources.isa_io);
+	request_resource(&iomem_resource, &ddb5476_resources.pci_io);
+	request_resource(&iomem_resource, &ddb5476_resources.isa_mem);
+	request_resource(&iomem_resource, &ddb5476_resources.pci_mem);
+	request_resource(&iomem_resource, &ddb5476_resources.boot);
+
+	pci_scan_bus(0, &nile4_pci_ops, NULL);
+	ddb5476_pci_fixup();
+	pci_assign_unassigned_resources();
+	pcibios_fixup_irqs();
+}
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+	/* [jsun] we don't know how to fix sub-buses yet */
+	if (bus->number == 0) {
+		bus->resource[1] = &ddb5476_resources.pci_mem;
+	}
+}
+
+char *pcibios_setup(char *str)
+{
+	return str;
+}
+
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus,
+				      struct pbus_set_ranges_data *ranges)
+{
+	/*
+	 * our caller figure out range by going through the dev structures.  
+	 * I guess this is the place to fix things up if the bus is using a 
+	 * different view of the addressing space.
+	 */
+
+#if 0	/*  original DDB5074 code */
+	   if (bus->number == 0) {
+	   ranges->io_start -= bus->resource[0]->start;
+	   ranges->io_end -= bus->resource[0]->start;
+	   ranges->mem_start -= bus->resource[1]->start;
+	   ranges->mem_end -= bus->resource[1]->start;
+	   }
+#endif
+}
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	/*
+	 *  Don't touch the Nile 4
+	 */
+	if (dev->vendor == PCI_VENDOR_ID_NEC &&
+	    dev->device == PCI_DEVICE_ID_NEC_VRC5476) return 0;
+
+	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;
+}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+	return pcibios_enable_resources(dev);
+}
+
+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;
+		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);
+	}
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+			    unsigned long size)
+{
+	struct pci_dev *dev = data;
+
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long start = res->start;
+
+		/* We need to avoid collisions with `mirrored' VGA ports
+		   and other strange ISA hardware, so we always want the
+		   addresses kilobyte aligned.  */
+		if (size > 0x100) {
+			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+			       " (%ld bytes)\n", dev->slot_name,
+			       dev->resource - res, size);
+		}
+
+		start = (start + 1024 - 1) & ~(1024 - 1);
+		res->start = start;
+	}
+}
+
+struct pci_fixup pcibios_fixups[] = { {0} };
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5476/prom.c linux/arch/mips/ddb5476/prom.c
--- v2.4.3/linux/arch/mips/ddb5476/prom.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/prom.c	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,43 @@
+/*
+ *  arch/mips/ddb5476/prom.c -- NEC DDB Vrc-5476 PROM routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ *
+ *   	Jun Sun - modified for DDB5476.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+
+char arcs_cmdline[COMMAND_LINE_SIZE];
+
+/* [jsun@junsun.net] PMON passes arguments in C main() style */
+void __init prom_init(int argc, const char **arg)
+{
+	int i;
+
+	/* arg[0] is "g", the rest is boot parameters */
+	arcs_cmdline[0] = '\0';
+	for (i = 1; i < argc; i++) {
+		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+		    >= sizeof(arcs_cmdline))
+			break;
+		strcat(arcs_cmdline, arg[i]);
+		strcat(arcs_cmdline, " ");
+	}
+
+	mips_machgroup = MACH_GROUP_NEC_DDB;
+	mips_machtype = MACH_NEC_DDB5476;
+	/* 64 MB non-upgradable */
+	add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5476/setup.c linux/arch/mips/ddb5476/setup.c
--- v2.4.3/linux/arch/mips/ddb5476/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/setup.c	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,375 @@
+/*
+ *  arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/console.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+#include <linux/pc_keyb.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/addrspace.h>
+#include <asm/bcache.h>
+#include <asm/keyboard.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/nile4.h>
+
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void rs_kgdb_hook(int);
+extern void breakpoint(void);
+#endif
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+extern void console_setup(char *);
+#endif
+
+extern struct ide_ops std_ide_ops;
+extern struct rtc_ops ddb_rtc_ops;
+extern struct kbd_ops std_kbd_ops;
+
+static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
+
+static void ddb_machine_restart(char *command)
+{
+	u32 t;
+
+	/* PCI cold reset */
+	t = nile4_in32(NILE4_PCICTRL + 4);
+	t |= 0x40000000;
+	nile4_out32(NILE4_PCICTRL + 4, t);
+	/* CPU cold reset */
+	t = nile4_in32(NILE4_CPUSTAT);
+	t |= 1;
+	nile4_out32(NILE4_CPUSTAT, t);
+	/* Call the PROM */
+	back_to_prom();
+}
+
+static void ddb_machine_halt(void)
+{
+	printk("DDB Vrc-5476 halted.\n");
+	while (1);
+}
+
+static void ddb_machine_power_off(void)
+{
+	printk("DDB Vrc-5476 halted. Please turn off the power.\n");
+	while (1);
+}
+
+extern void ddb_irq_setup(void);
+
+void (*board_time_init) (struct irqaction * irq);
+
+
+static void __init ddb_time_init(struct irqaction *irq)
+{
+	/* set the clock to 1 Hz */
+	nile4_out32(NILE4_T2CTRL, 1000000);
+	/* enable the General-Purpose Timer */
+	nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
+	/* reset timer */
+	nile4_out32(NILE4_T2CNTR, 0);
+	/* enable interrupt */
+	nile4_enable_irq(NILE4_INT_GPT);
+	i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
+}
+
+static struct {
+	struct resource dma1;
+	struct resource pic1;
+	struct resource timer;
+	struct resource rtc;
+	struct resource dma_page_reg;
+	struct resource pic2;
+	struct resource dma2;
+} ddb5476_ioport = {
+	{
+	"dma1", 0x00, 0x1f, IORESOURCE_BUSY}, {
+	"pic1", 0x20, 0x3f, IORESOURCE_BUSY}, {
+	"timer", 0x40, 0x5f, IORESOURCE_BUSY}, {
+	"rtc", 0x70, 0x7f, IORESOURCE_BUSY}, {
+	"dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, {
+	"pic2", 0xa0, 0xbf, IORESOURCE_BUSY}, {
+	"dma2", 0xc0, 0xdf, IORESOURCE_BUSY}
+};
+
+static struct {
+	struct resource nile4;
+} ddb5476_iomem = {
+	{ "Nile 4", NILE4_BASE, NILE4_BASE + NILE4_SIZE - 1, IORESOURCE_BUSY}
+};
+
+void __init ddb_setup(void)
+{
+	extern int panic_timeout;
+
+	irq_setup = ddb_irq_setup;
+	mips_io_port_base = NILE4_PCI_IO_BASE;
+	isa_slot_offset = NILE4_PCI_MEM_BASE;
+	board_time_init = ddb_time_init;
+
+	_machine_restart = ddb_machine_restart;
+	_machine_halt = ddb_machine_halt;
+	_machine_power_off = ddb_machine_power_off;
+
+	/* request io port/mem resources  */
+	if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
+	    request_resource(&ioport_resource, &ddb5476_ioport.pic1) ||
+	    request_resource(&ioport_resource, &ddb5476_ioport.timer) ||
+	    request_resource(&ioport_resource, &ddb5476_ioport.rtc) ||
+	    request_resource(&ioport_resource,
+			     &ddb5476_ioport.dma_page_reg)
+	    || request_resource(&ioport_resource, &ddb5476_ioport.pic2)
+	    || request_resource(&ioport_resource, &ddb5476_ioport.dma2)
+	    || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) {
+		printk
+		    ("ddb_setup - requesting oo port resources failed.\n");
+		for (;;);
+	}
+#ifdef CONFIG_BLK_DEV_IDE
+	ide_ops = &std_ide_ops;
+#endif
+	rtc_ops = &ddb_rtc_ops;
+
+#ifdef CONFIG_PC_KEYB
+	kbd_ops = &std_kbd_ops;
+#endif
+
+	/* Reboot on panic */
+	panic_timeout = 180;
+
+	/* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
+	/* *(long*)0xbfa00218 = 0x8; */
+
+#ifdef CONFIG_FB
+	conswitchp = &dummy_con;
+#endif
+
+
+	/* board initialization stuff - non-fundamental, but need to be set
+	 * before kernel runs */
+
+	/* setup I/O space */
+	nile4_set_pdar(NILE4_PCIW0,
+		       PHYSADDR(NILE4_PCI_IO_BASE), 0x02000000, 32, 0, 0);
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
+
+	/* map config space to 0xa8000000, 128MB */
+	nile4_set_pdar(NILE4_PCIW1,
+		       PHYSADDR(NILE4_PCI_CFG_BASE), 0x08000000, 32, 0, 0);
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, 0x0);
+
+	/* ----- M1543 PCI setup ------ */
+
+	/* we know M1543 PCI-ISA controller is at addr:18 */
+	/* xxxx1010 makes USB at addr:13 and PMU at addr:14 */
+	*(volatile unsigned char *) 0xa8040072 &= 0xf0;
+	*(volatile unsigned char *) 0xa8040072 |= 0xa;
+
+	/* setup USB interrupt to IRQ 9, (bit 0:3 - 0001)
+	 * no IOCHRDY signal, (bit 7 - 1)
+	 * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1)
+	 * Bypass USB Master INTAJ level to edge conversion (bit 4 - 0)
+	 */
+	*(unsigned char *) 0xa8040074 = 0xc1;
+
+	/* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011)
+	 * SCI routing to IRQ 13 disabled (bit 7 - 1)
+	 * SCI interrupt level to edge conversion bypassed (bit 4 - 0)
+	 */
+	*(unsigned char *) 0xa8040076 = 0x83;
+
+	/* setup IDE controller
+	 * enable IDE controller (bit 6 - 1)
+	 * IDE IDSEL to be addr:24 (bit 4:5 - 11)
+	 * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
+	 * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0)
+	 * primary IRQ is 14, secondary is 15 (bit 1:0 - 01
+	 */
+	// *(unsigned char*)0xa8040058 = 0x71;
+	// *(unsigned char*)0xa8040058 = 0x79;
+	// *(unsigned char*)0xa8040058 = 0x74;              // use SIRQ, primary tri-state
+	*(unsigned char *) 0xa8040058 = 0x75;	// primary tri-state
+
+#if 0
+	/* this is not necessary if M5229 does not use SIRQ */
+	*(unsigned char *) 0xa8040044 = 0x0d;	// primary to IRQ 14
+	*(unsigned char *) 0xa8040075 = 0x0d;	// secondary to IRQ 14
+#endif
+
+	/* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */
+	/* M5229 IDSEL is addr:24; see above setting */
+	*(unsigned char *) 0xa9000050 |= 0x1;
+
+	/* enable bus master (bit 2)  and IO decoding  (bit 0) */
+	*(unsigned char *) 0xa9000004 |= 0x5;
+
+	/* enable native, copied from arch/ppc/k2boot/head.S */
+	/* TODO - need volatile, need to be portable */
+	*(unsigned char *) 0xa9000009 = 0xff;
+
+	/* ----- end of M1543 PCI setup ------ */
+
+	/* ----- reset on-board ether chip  ------ */
+	*((volatile u32 *) 0xa8020004) |= 1;	/* decode I/O */
+	*((volatile u32 *) 0xa8020010) = 0;	/* set BAR address */
+
+	/* send reset command */
+	*((volatile u32 *) 0xa6000000) = 1;	/* do a soft reset */
+
+	/* disable ether chip */
+	*((volatile u32 *) 0xa8020004) = 0;	/* disable any decoding */
+
+	/* put it into sleep */
+	*((volatile u32 *) 0xa8020040) = 0x80000000;
+
+	/* ----- end of reset on-board ether chip  ------ */
+
+	/* ----- set pci window 1 to pci memory space -------- */
+	nile4_set_pdar(NILE4_PCIW1,
+		       PHYSADDR(NILE4_PCI_MEM_BASE), 0x08000000, 32, 0, 0);
+	// nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0x08000000);
+
+}
+
+#define USE_NILE4_SERIAL	0
+
+#if USE_NILE4_SERIAL
+#define ns16550_in(reg)		nile4_in8((reg)*8)
+#define ns16550_out(reg, val)	nile4_out8((reg)*8, (val))
+#else
+#define NS16550_BASE		(NILE4_PCI_IO_BASE+0x03f8)
+static inline u8 ns16550_in(u32 reg)
+{
+	return *(volatile u8 *) (NS16550_BASE + reg);
+}
+
+static inline void ns16550_out(u32 reg, u8 val)
+{
+	*(volatile u8 *) (NS16550_BASE + reg) = val;
+}
+#endif
+
+#define NS16550_RBR		0
+#define NS16550_THR		0
+#define NS16550_DLL		0
+#define NS16550_IER		1
+#define NS16550_DLM		1
+#define NS16550_FCR		2
+#define NS16550_IIR		2
+#define NS16550_LCR		3
+#define NS16550_MCR		4
+#define NS16550_LSR		5
+#define NS16550_MSR		6
+#define NS16550_SCR		7
+
+#define NS16550_LSR_DR		0x01	/* Data ready */
+#define NS16550_LSR_OE		0x02	/* Overrun */
+#define NS16550_LSR_PE		0x04	/* Parity error */
+#define NS16550_LSR_FE		0x08	/* Framing error */
+#define NS16550_LSR_BI		0x10	/* Break */
+#define NS16550_LSR_THRE	0x20	/* Xmit holding register empty */
+#define NS16550_LSR_TEMT	0x40	/* Xmitter empty */
+#define NS16550_LSR_ERR		0x80	/* Error */
+
+
+void _serinit(void)
+{
+#if USE_NILE4_SERIAL
+	ns16550_out(NS16550_LCR, 0x80);
+	ns16550_out(NS16550_DLM, 0x00);
+	ns16550_out(NS16550_DLL, 0x36);	/* 9600 baud */
+	ns16550_out(NS16550_LCR, 0x00);
+	ns16550_out(NS16550_LCR, 0x03);
+	ns16550_out(NS16550_FCR, 0x47);
+#else
+	/* done by PMON */
+#endif
+}
+
+void _putc(char c)
+{
+	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+	ns16550_out(NS16550_THR, c);
+	if (c == '\n') {
+		while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+		ns16550_out(NS16550_THR, '\r');
+	}
+}
+
+void _puts(const char *s)
+{
+	char c;
+
+	while ((c = *s++))
+		_putc(c);
+}
+
+char _getc(void)
+{
+	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
+
+	return ns16550_in(NS16550_RBR);
+}
+
+int _testc(void)
+{
+	return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
+}
+
+
+/*
+ *  Hexadecimal 7-segment LED
+ */
+void ddb5476_led_hex(int hex)
+{
+	outb(hex, 0x80);
+}
+
+
+/*
+ *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
+ */
+struct pci_dev *pci_pmu = NULL;
+
+void ddb5476_led_d2(int on)
+{
+	u8 t;
+
+	if (pci_pmu) {
+		pci_read_config_byte(pci_pmu, 0x7e, &t);
+		if (on)
+			t &= 0x7f;
+		else
+			t |= 0x80;
+		pci_write_config_byte(pci_pmu, 0x7e, t);
+	}
+}
+
+void ddb5476_led_d3(int on)
+{
+	u8 t;
+
+	if (pci_pmu) {
+		pci_read_config_byte(pci_pmu, 0x7e, &t);
+		if (on)
+			t &= 0xbf;
+		else
+			t |= 0x40;
+		pci_write_config_byte(pci_pmu, 0x7e, t);
+	}
+}
diff -u --recursive --new-file v2.4.3/linux/arch/mips/ddb5476/time.c linux/arch/mips/ddb5476/time.c
--- v2.4.3/linux/arch/mips/ddb5476/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/time.c	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,32 @@
+/*
+ *  arch/mips/ddb5074/time.c -- Timer routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/init.h>
+
+#include <asm/mc146818rtc.h>
+
+static unsigned char ddb_rtc_read_data(unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	return inb_p(RTC_PORT(1));
+}
+
+static void ddb_rtc_write_data(unsigned char data, unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	outb_p(data, RTC_PORT(1));
+}
+
+static int ddb_rtc_bcd_mode(void)
+{
+	return 1;
+}
+
+struct rtc_ops ddb_rtc_ops = {
+	ddb_rtc_read_data,
+	ddb_rtc_write_data,
+	ddb_rtc_bcd_mode
+};
diff -u --recursive --new-file v2.4.3/linux/arch/mips/dec/Makefile linux/arch/mips/dec/Makefile
--- v2.4.3/linux/arch/mips/dec/Makefile	Thu Feb 24 22:52:30 2000
+++ linux/arch/mips/dec/Makefile	Fri Apr 13 20:26:07 2001
@@ -7,30 +7,20 @@
 #
 
 .S.s:
-	$(CPP) $(CFLAGS) $< -o $*.s
+	$(CPP) $(AFLAGS) $< -o $@
 .S.o:
-	$(CC) $(CFLAGS) -c $< -o $*.o
+	$(CC) $(AFLAGS) -c $< -o $@
 
-all: dec.o
 O_TARGET := dec.o
-O_OBJS	 := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o
 
-ifdef CONFIG_PROM_CONSOLE
-O_OBJS   += promcon.o
-endif
+all: dec.o
 
-ifdef CONFIG_SERIAL
-O_OBJS   += serial.o
-endif
+export-objs := wbflush.o
+obj-y	 := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o wbflush.o
 
-ifeq ($(CONFIG_MODULES),y)
- OX_OBJS  = wbflush.o
-else
- O_OBJS   += wbflush.o
-endif
+obj-$(CONFIG_PROM_CONSOLE)	+= promcon.o
+obj-$(CONFIG_SERIAL)		+= serial.o
 
 int-handler.o:	int-handler.S
-
-clean:
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.3/linux/arch/mips/dec/boot/Makefile linux/arch/mips/dec/boot/Makefile
--- v2.4.3/linux/arch/mips/dec/boot/Makefile	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/dec/boot/Makefile	Fri Apr 13 20:26:07 2001
@@ -18,7 +18,8 @@
 all: dec_boot.o
 
 O_TARGET := dec_boot.o
-O_OBJS	 := decstation.o
+
+obj-y	 := decstation.o
 
 clean:
 	rm -f nbImage
diff -u --recursive --new-file v2.4.3/linux/arch/mips/defconfig linux/arch/mips/defconfig
--- v2.4.3/linux/arch/mips/defconfig	Sun Mar  4 14:30:18 2001
+++ linux/arch/mips/defconfig	Fri Apr 13 20:26:07 2001
@@ -16,16 +16,17 @@
 # CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 CONFIG_SGI_IP22=y
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 CONFIG_ARC32=y
 CONFIG_PC_KEYB=y
 CONFIG_SGI=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_PCI is not set
 
 #
@@ -84,17 +85,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -111,10 +118,8 @@
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -131,6 +136,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -152,6 +158,7 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
@@ -192,14 +199,14 @@
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -229,6 +236,8 @@
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -283,8 +292,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -299,11 +306,13 @@
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -334,6 +343,11 @@
 # USB support
 #
 # CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.4.3/linux/arch/mips/defconfig-cobalt linux/arch/mips/defconfig-cobalt
--- v2.4.3/linux/arch/mips/defconfig-cobalt	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/defconfig-cobalt	Fri Apr 13 20:26:07 2001
@@ -17,18 +17,18 @@
 CONFIG_COBALT_28=y
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
-# CONFIG_ISA is not set
 CONFIG_COBALT_27=y
 CONFIG_COBALT_LCD=y
 CONFIG_COBALT_SERIAL=y
 CONFIG_PCI=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 
 #
 # Loadable module support
@@ -85,22 +85,26 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_BLK_DEV_LOOP=m
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_BOOT is not set
-# CONFIG_AUTODETECT_RAID is not set
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
 
 #
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
 # Networking options
 #
 # CONFIG_PACKET is not set
@@ -112,13 +116,11 @@
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 CONFIG_IP_MROUTE=y
 # CONFIG_IP_PIMSM_V1 is not set
 # CONFIG_IP_PIMSM_V2 is not set
-CONFIG_IP_ALIAS=y
 # CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
 # CONFIG_IPV6 is not set
@@ -130,13 +132,13 @@
 #
 CONFIG_IPX=m
 # CONFIG_IPX_INTERN is not set
-# CONFIG_SPX is not set
 CONFIG_ATALK=m
 # CONFIG_DECNET is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -171,6 +173,7 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
@@ -194,15 +197,14 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 CONFIG_SCSI_AIC7XXX=y
-# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
-# CONFIG_AIC7XXX_PROC_STATS is not set
 CONFIG_AIC7XXX_RESET_DELAY=5
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
@@ -214,8 +216,6 @@
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 CONFIG_SCSI_NCR53C8XX=y
 # CONFIG_SCSI_SYM53C8XX is not set
@@ -233,6 +233,8 @@
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
@@ -265,6 +267,7 @@
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_NET_SB1000 is not set
 
 #
@@ -277,6 +280,7 @@
 # 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
 # CONFIG_NET_PCI is not set
 # CONFIG_NET_POCKET is not set
@@ -284,8 +288,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -326,6 +331,7 @@
 CONFIG_ISDN_PPP=y
 CONFIG_ISDN_PPP_VJ=y
 CONFIG_ISDN_MPP=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
 CONFIG_ISDN_AUDIO=y
 # CONFIG_ISDN_TTY_FAX is not set
 
@@ -353,6 +359,7 @@
 # CONFIG_HISAX_NO_LLC is not set
 # CONFIG_HISAX_NO_KEYPAD is not set
 CONFIG_HISAX_1TR6=y
+# CONFIG_HISAX_NI1 is not set
 
 #
 #   HiSax supported cards
@@ -374,6 +381,7 @@
 # CONFIG_HISAX_SPORTSTER is not set
 # CONFIG_HISAX_MIC is not set
 # CONFIG_HISAX_NETJET is not set
+# CONFIG_HISAX_NETJET_U is not set
 # CONFIG_HISAX_NICCY is not set
 # CONFIG_HISAX_ISURF is not set
 # CONFIG_HISAX_HSTSAPHIR is not set
@@ -383,6 +391,7 @@
 # CONFIG_HISAX_HFC_PCI is not set
 # CONFIG_HISAX_W6692 is not set
 # CONFIG_HISAX_HFC_SX is not set
+# CONFIG_HISAX_SEDLBAUER_CS is not set
 
 #
 # Active ISDN cards
@@ -393,8 +402,8 @@
 # CONFIG_ISDN_DRV_ACT2000 is not set
 # CONFIG_ISDN_DRV_EICON is not set
 # CONFIG_ISDN_CAPI is not set
-# CONFIG_ISDN_CAPI_MIDDLEWARE is not set
 # CONFIG_HYSDN is not set
+# CONFIG_HYSDN_CAPI is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -425,6 +434,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -434,11 +447,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -447,8 +455,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -456,6 +469,8 @@
 CONFIG_QUOTA=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -503,6 +518,7 @@
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
@@ -510,8 +526,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -520,6 +534,7 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
+CONFIG_SMB_NLS=y
 CONFIG_NLS=y
 
 #
@@ -569,6 +584,11 @@
 # USB support
 #
 # CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.4.3/linux/arch/mips/defconfig-ddb5476 linux/arch/mips/defconfig-ddb5476
--- v2.4.3/linux/arch/mips/defconfig-ddb5476	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/defconfig-ddb5476	Fri Apr 13 20:26:07 2001
@@ -0,0 +1,541 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_SMP is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Machine selection
+#
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_NINO is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_MOMENCO_OCELOT is not set
+CONFIG_DDB5476=y
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+CONFIG_I8259=y
+CONFIG_ISA=y
+CONFIG_PCI=y
+CONFIG_PC_KEYB=y
+CONFIG_ROTTEN_IRQ=y
+CONFIG_EISA=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R3912 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_R5000 is not set
+CONFIG_CPU_R5432=y
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
+
+#
+# General setup
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_FPU_EMULATOR=y
+CONFIG_KCORE_ELF=y
+CONFIG_ELF_KERNEL=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_IDEDMA_PCI is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD7409 is not set
+# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_BLK_DEV_OSB4 is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# 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
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_TULIP=y
+# 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_NATSEMI is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139TOO is not set
+# CONFIG_RTL8129 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_CLGEN is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+CONFIG_FB_