diff -u --recursive --new-file v2.4.0/linux/CREDITS linux/CREDITS
--- v2.4.0/linux/CREDITS	Sun Dec 31 09:27:57 2000
+++ linux/CREDITS	Wed Jan 17 13:27:16 2001
@@ -2353,10 +2353,11 @@
 D: Dosemu
 
 N: Hannu Savolainen
-E: hannu@voxware.pp.fi
-D: Kernel sound drivers
-S: Hiekkalaiturintie 3 A 8
-S: 00980 Helsinki
+E: hannu@opensound.com
+D: Maintainer of the sound drivers until 2.1.x days.
+D: Original compressed boot image support.
+S: Valurink. 4A11
+S: 03600 Karkkila
 S: Finland
 
 N: Eric Schenk
diff -u --recursive --new-file v2.4.0/linux/Documentation/Changes linux/Documentation/Changes
--- v2.4.0/linux/Documentation/Changes	Mon Jan  1 10:00:04 2001
+++ linux/Documentation/Changes	Mon Jan 22 13:30:21 2001
@@ -56,7 +56,7 @@
 o  e2fsprogs              1.19                    # tune2fs --version
 o  pcmcia-cs              3.1.21                  # cardmgr -V
 o  PPP                    2.4.0                   # pppd --version
-o  isdn4k-utils           3.1beta7                # isdnctrl 2>&1|grep version
+o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
 			  
 Kernel compilation
 ==================
@@ -335,9 +335,9 @@
 
 Netfilter
 ---------
-o  <http://netfilter.filewatcher.org/iptables-1.1.1.tar.bz2>
-o  <http://www.samba.org/netfilter/iptables-1.1.1.tar.bz2>
-o  <http://netfilter.kernelnotes.org/iptables-1.1.1.tar.bz2>
+o  <http://netfilter.filewatcher.org/iptables-1.2.tar.bz2>
+o  <http://netfilter.samba.org/iptables-1.2.tar.bz2>
+o  <http://netfilter.kernelnotes.org/iptables-1.2.tar.bz2>
 
 Ip-route2
 ---------
diff -u --recursive --new-file v2.4.0/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.4.0/linux/Documentation/Configure.help	Thu Jan  4 13:00:55 2001
+++ linux/Documentation/Configure.help	Mon Jan 29 13:16:00 2001
@@ -1450,15 +1450,6 @@
   want), say M here and read Documentation/modules.txt. The module
   will be called lvm-mod.o.
 
-Logical Volume Manager /proc file system information
-CONFIG_LVM_PROC_FS
-  If you say Y here, you are able to access overall Logical Volume
-  Manager, Volume Group, Logical and Physical Volume information in
-  /proc/lvm.
-
-  To use this option, you have to check, that the "/proc file system
-  support" (CONFIG_PROC_FS) is enabled too.
-
 Multiple devices driver support
 CONFIG_BLK_DEV_MD
   This driver lets you combine several hard disk partitions into one
@@ -1565,20 +1556,6 @@
 
   If unsure, say Y.
 
-RAID Boot support
-CONFIG_MD_BOOT
-  To boot with an initial raid volume (any type) you can select
-  autodetect, or answer Y here and appropriate options to the kernel
-  at boot time.
-  For lilo and loadlin options see the file Documentation/md.txt.
-
-RAID AutoDetect support
-CONFIG_AUTODETECT_RAID
-  An alternative to "Raid Boot support" is autodetect support.
-  With this selected, any partitons of type 0xFD will be considered for
-  inclusion in a RAID array.  Information in the RAID-superblock on
-  the partition will determine how it is included.
-
 Support for Acer PICA 1 chipset
 CONFIG_ACER_PICA_61
   This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
@@ -2069,6 +2046,72 @@
 
   If in doubt, say N.
 
+IP6 tables support (required for filtering/masq/NAT)
+CONFIG_IP6_NF_IPTABLES
+  ip6tables is a general, extensible packet identification framework.
+  Currently only the packet filtering and packet mangling subsystem
+  for IPv6 use this, but connection tracking is going to follow.
+  Say 'Y' or 'M' here if you want to use either of those.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+IPv6 limit match support
+CONFIG_IP6_NF_MATCH_LIMIT
+  limit matching allows you to control the rate at which a rule can be
+  matched: mainly useful in combination with the LOG target ("LOG
+  target support", below) and to avoid some Denial of Service attacks.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+MAC address match support
+CONFIG_IP6_NF_MATCH_MAC
+  mac matching allows you to match packets based on the source
+  ethernet address of the packet.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+netfilter mark match support
+CONFIG_IP6_NF_MATCH_MARK
+  Netfilter mark matching allows you to match packets based on the
+  `nfmark' value in the packet.  This can be set by the MARK target
+  (see below).
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+Packet filtering
+CONFIG_IP6_NF_FILTER
+  Packet filtering defines a table `filter', which has a series of
+  rules for simple packet filtering at local input, forwarding and
+  local output.  See the man page for iptables(8).
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+Packet mangling
+CONFIG_IP6_NF_MANGLE
+  This option adds a `mangle' table to iptables: see the man page for
+  iptables(8).  This table is used for various packet alterations
+  which can effect how the packet is routed.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+MARK target support
+CONFIG_IP6_NF_TARGET_MARK
+  This option adds a `MARK' target, which allows you to create rules
+  in the `mangle' table which alter the netfilter mark (nfmark) field
+  associated with the packet packet prior to routing. This can change
+  the routing method (see `IP: use netfilter MARK value as routing
+  key') and can also be used by other subsystems to change their
+  behavior.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
 SYN flood protection
 CONFIG_SYN_COOKIES
   Normal TCP/IP networking is open to an attack known as "SYN
@@ -2625,13 +2668,14 @@
 
   One well known example of this is PCMCIA- or PC-cards, credit-card
   size devices such as network cards, modems or hard drives which are
-  plugged into slots found on all modern laptop computers.
+  plugged into slots found on all modern laptop computers.  Another
+  example, used on modern desktops as well as laptops, is USB.
 
-  Another example, used on modern desktops as well as laptops, is USB.
-  Enable HOTPLUG with USB and KMOD, and your kernel will automatically
-  call out to a user mode "policy agent" to load modules and set up
-  software needed to use USB devices you plug in.  Get agent software
-  (at http://www.linux-usb.org/policy.html) and install it.
+  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
+  software (at http://linux-hotplug.sourceforge.net) and install it.
+  Then your kernel will automatically call out to a user mode "policy
+  agent" (/sbin/hotplug) to load modules and set up software needed
+  to use devices as you hotplug them.
 
 PCMCIA/Cardbus support
 CONFIG_PCMCIA
@@ -10745,6 +10789,46 @@
   called minix.o. Note that the file system of your root partition
   (the one containing the directory /) cannot be compiled as a module.
 
+Reiserfs support
+CONFIG_REISERFS_FS
+
+  Stores not just filenames but the files themselves in a balanced
+  tree.  Uses journaling.
+
+  Balanced trees are more efficient than traditional
+  filesystem architectural foundations.
+
+  You can use reiserfs in all cases where you use the ext2fs file
+  system, and you will gain in speed and disk space.  It has fewer
+  worst case performance situations than other file systems
+  because balanced trees are hardier creatures than other algorithms
+  are (if that is not technical enough, read www.namesys.com....:-) )
+
+  It is more easily extended to have features currently found in
+  database and keyword search systems than block allocation based
+  filesystems are.  The next version will be so extended, and will
+  support plugins consistent with our motto ``It takes more than a
+  license to make source code open.''
+
+  Read www.namesys.com to learn more about reiserfs.
+
+  Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com.
+
+  If you like it, you can pay us to add new features to it that you
+  need, buy a support contract, or pay us to port it to another OS.
+
+Enable Reiserfs consistency checks
+CONFIG_REISERFS_CHECK
+  If you set this to yes, then ReiserFS will perform every check it
+  can possibly imagine of its internal consistency throughout its
+  operation.  It will also go substantially slower.  More than once we
+  have forgotten that this was on, and then gone despondent over the
+  latest benchmarks.:-) Use of this option allows our team to go all
+  out in checking for consistency when debugging without fear of its
+  effect on end users.  If you are on the verge of sending in a bug
+  report, say yes and you might get a useful error message.  Almost
+  everyone should say no.
+
 Second extended fs support
 CONFIG_EXT2_FS
   This is the de facto standard Linux file system (method to organize
@@ -13225,7 +13309,7 @@
 
   This support requires an ACPI compliant platform (hardware/firmware).
   If both ACPI and Advanced Power Management (APM) support are
-  configured, ACPI is used.
+  configured, whichever is loaded first shall be used.
 
   This code DOES NOT currently provide a complete OSPM implementation --
   it has not yet reached APM's level of functionality. When fully
@@ -14619,6 +14703,14 @@
   This enables Van Jacobson header compression for synchronous PPP.
   Say Y if the other end of the connection supports it.
 
+CONFIG_ISDN_PPP_BSDCOMP
+  Support for the BSD-Compress compression method for PPP, which uses
+  the LZW compression method to compress each PPP packet before it is
+  sent over the wire. The machine at the other end of the PPP link
+  (usually your ISP) has to support the BSD-Compress compression
+  method as well for this to be useful. Even if they don't support it,
+  it is safe to say Y here.
+
 Support audio via ISDN
 CONFIG_ISDN_AUDIO
   If you say Y here, the modem-emulator will support a subset of the
@@ -16953,6 +17045,20 @@
 
   If you do not have a CompactPCI model CP1400 or CP1500, or
   another UltraSPARC-IIi-cEngine boardset with a 7-segment display,
+  you should say N to this option. 
+
+CP1XXX Hardware Watchdog support
+CONFIG_WATCHDOG_CP1XXX
+  This is the driver for the hardware watchdog timers present on
+  Sun Microsystems CompactPCI models CP1400 and CP1500.
+
+  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 cpwatchdog.o. If you want to compile it
+  as a module, say M here and read Documentation/modules.txt.
+
+  If you do not have a CompactPCI model CP1400 or CP1500, or
+  another UltraSPARC-IIi-cEngine boardset with hardware watchdog,
   you should say N to this option. 
 
 IA-64 system type
diff -u --recursive --new-file v2.4.0/linux/Documentation/cachetlb.txt linux/Documentation/cachetlb.txt
--- v2.4.0/linux/Documentation/cachetlb.txt	Mon Dec 11 12:37:04 2000
+++ linux/Documentation/cachetlb.txt	Mon Jan 22 13:30:21 2001
@@ -167,7 +167,7 @@
 
 	This interface flushes an entire user address space from
 	the caches.  That is, after running, there will be no cache
-	lines assosciated with 'mm'.
+	lines associated with 'mm'.
 
 	This interface is used to handle whole address space
 	page table operations such as what happens during
@@ -209,7 +209,7 @@
 The biggest problem is that of virtual aliasing in the data cache
 of a processor.
 
-Is your port subsceptible to virtual aliasing in it's D-cache?
+Is your port susceptible to virtual aliasing in it's D-cache?
 Well, if your D-cache is virtually indexed, is larger in size than
 PAGE_SIZE, and does not prevent multiple cache lines for the same
 physical address from existing at once, you have this problem.
@@ -221,6 +221,9 @@
 processes to mmap shared memory at address which are a multiple of
 this value.
 
+NOTE: This does not fix shared mmaps, check out the sparc64 port for
+one way to solve this (in particular SPARC_FLAG_MMAPSHARED).
+
 Next, you have two methods to solve the D-cache aliasing issue for all
 other cases.  Please keep in mind that fact that, for a given page
 mapped into some user address space, there is always at least one more
@@ -240,7 +243,7 @@
 	The physical page 'page' is about to be place into the
 	user address space of a process.  If it is possible for
 	stores done recently by the kernel into this physical
-	page, to not be visible to an arbitray mapping in userspace,
+	page, to not be visible to an arbitrary mapping in userspace,
 	you must flush this page from the D-cache.
 
 	If the D-cache is writeback in nature, the dirty data (if
@@ -266,7 +269,7 @@
 
 	For example, a port may temporarily map 'from' and 'to' to
 	kernel virtual addresses during the copy.  The virtual address
-	for these two pages is choosen in such a way that the kernel
+	for these two pages is chosen in such a way that the kernel
 	load/store instructions happen to virtual addresses which are
 	of the same "color" as the user mapping of the page.  Sparc64
 	for example, uses this technique.
@@ -306,7 +309,7 @@
 	simply be defined as a nop on that architecture.
 
         There is a bit set aside in page->flags (PG_arch_1) as
-	"architecture private".  The kernel guarentees that,
+	"architecture private".  The kernel guarantees that,
 	for pagecache pages, it will clear this bit when such
 	a page first enters the pagecache.
 
@@ -323,7 +326,14 @@
 	update_mmu_cache(), a check is made of this flag bit, and if
 	set the flush is done and the flag bit is cleared.
 
-XXX Not documented: flush_icache_page(), need to talk to Paul
-                    Mackerras, David Mosberger-Tang, et al.
-		    to see what the expected semantics of this
-		    interface are.  -DaveM
+  void flush_icache_range(unsigned long start, unsigned long end)
+  	When the kernel stores into addresses that it will execute
+	out of (eg when loading modules), this function is called.
+
+	If the icache does not snoop stores then this routine will need
+	to flush it.
+
+  void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+	All the functionality of flush_icache_page can be implemented in
+	flush_dcache_page and update_mmu_cache. In 2.5 the hope is to
+	remove this interface completely.
diff -u --recursive --new-file v2.4.0/linux/Documentation/usb/hotplug.txt linux/Documentation/usb/hotplug.txt
--- v2.4.0/linux/Documentation/usb/hotplug.txt	Sun Nov 12 20:45:19 2000
+++ linux/Documentation/usb/hotplug.txt	Tue Jan 16 12:02:51 2001
@@ -1,4 +1,4 @@
-USB HOTPLUGGING
+LINUX HOTPLUGGING
 
 In hotpluggable busses like USB (and Cardbus PCI), end-users plug devices
 into the bus with power on.  In most cases, users expect the devices to become
@@ -8,7 +8,7 @@
       loading a kernel module; newer drivers can use modutils to
       publish their device (and class) support to user utilities.
 
-    - Bind a driver to that device.  That's done using the USB
+    - Bind a driver to that device.  Bus frameworks do that using a
       device driver's probe() routine.
     
     - Tell other subsystems to configure the new device.  Print
@@ -26,6 +26,10 @@
 such programs are called "policy agents" here.  Typically they involve
 shell scripts that dispatch to more familiar administration tools.
 
+Because some of those actions rely on information about drivers (metadata)
+that is currently available only when the drivers are dynamically linked,
+you get the best hotplugging when you configure a highly modular system.
+
 
 KERNEL HOTPLUG HELPER (/sbin/hotplug)
 
@@ -40,9 +44,14 @@
 dispatch; any other argument and environment parameters are specified by
 the subsystem making that invocation.
 
-A reference implementation of a /sbin/hotplug script is available at the
-http://www.linux-usb.org website, which works USB for but also knows how to
-delegate to any /etc/hotplug/$TYPE.agent policy agent present.
+Hotplug software and other resources is available at:
+
+	http://linux-hotplug.sourceforge.net
+
+Mailing list information is also available at that site.
+
+
+--------------------------------------------------------------------------
 
 
 USB POLICY AGENT
diff -u --recursive --new-file v2.4.0/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt
--- v2.4.0/linux/Documentation/usb/usb-serial.txt	Thu Dec  7 16:13:38 2000
+++ linux/Documentation/usb/usb-serial.txt	Tue Jan 16 14:29:54 2001
@@ -223,7 +223,7 @@
   
   To enable the generic driver to recognize your device, build the driver
   as a module and load it by the following invocation:
-	insmod usb-serial vendor=0x#### product=0x####
+	insmod usbserial vendor=0x#### product=0x####
   where the #### is replaced with the hex representation of your device's
   vendor id and product id.
 
diff -u --recursive --new-file v2.4.0/linux/MAINTAINERS linux/MAINTAINERS
--- v2.4.0/linux/MAINTAINERS	Sun Dec 31 09:31:15 2000
+++ linux/MAINTAINERS	Sun Jan 28 13:37:18 2001
@@ -196,6 +196,12 @@
 W:	http://www.ocston.org/~tigran/patches/bfs
 S:	Maintained
 
+BLOCK LAYER
+P:	Jens Axboe
+M:	axboe@suse.de
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
 BTTV VIDEO4LINUX DRIVER
 P:	Gerd Knorr
 M:	kraxel@goldbach.in-berlin.de
diff -u --recursive --new-file v2.4.0/linux/Makefile linux/Makefile
--- v2.4.0/linux/Makefile	Thu Jan  4 13:48:13 2001
+++ linux/Makefile	Mon Jan 29 13:39:25 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 0
-EXTRAVERSION =
+SUBLEVEL = 1
+EXTRAVERSION =-pre12
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -457,9 +457,8 @@
 
 depend dep: dep-files
 
-# make checkconfig: Prune 'scripts' directory to avoid "false positives".
 checkconfig:
-	find * -name '*.[hcS]' -type f -print | grep -v scripts/ | sort | xargs $(PERL) -w scripts/checkconfig.pl
+	find * -name '*.[hcS]' -type f -print | sort | xargs $(PERL) -w scripts/checkconfig.pl
 
 checkhelp:
 	find * -name [cC]onfig.in -print | sort | xargs $(PERL) -w scripts/checkhelp.pl
diff -u --recursive --new-file v2.4.0/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v2.4.0/linux/arch/alpha/kernel/Makefile	Fri Dec 29 14:07:19 2000
+++ linux/arch/alpha/kernel/Makefile	Wed Jan 24 15:16:23 2001
@@ -23,7 +23,7 @@
 # FIXME!
 # These should be made conditional on the stuff that needs them!
 #
-obj-y	 += irq_i8259.o irq_srm.o irq_pyxis.o \
+obj-y	 += irq_i8259.o irq_srm.o \
 	    es1888.o smc37c669.o smc37c93x.o ns87312.o
 
 ifdef CONFIG_VGA_HOSE
@@ -43,7 +43,7 @@
 	    sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o sys_titan.o \
 	    sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
 	    sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_rx164.o \
-	    sys_wildfire.o core_wildfire.o
+	    sys_wildfire.o core_wildfire.o irq_pyxis.o
 
 else
 
@@ -93,6 +93,10 @@
 obj-$(CONFIG_ALPHA_SX164) += sys_sx164.o
 obj-$(CONFIG_ALPHA_TAKARA) += sys_takara.o
 obj-$(CONFIG_ALPHA_WILDFIRE) += sys_wildfire.o
+
+ifneq ($(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_RUFFIAN)$(CONFIG_ALPHA_SX164),)
+obj-y    += irq_pyxis.o
+endif
 
 endif # GENERIC
 
diff -u --recursive --new-file v2.4.0/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.4.0/linux/arch/alpha/kernel/osf_sys.c	Fri Aug 11 14:29:04 2000
+++ linux/arch/alpha/kernel/osf_sys.c	Wed Jan 24 15:16:23 2001
@@ -904,7 +904,6 @@
 extern int do_getitimer(int which, struct itimerval *value);
 extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
 asmlinkage int sys_utimes(char *, struct timeval *);
-extern int sys_wait4(pid_t, int *, int, struct rusage *);
 extern int do_adjtimex(struct timex *);
 
 struct timeval32
diff -u --recursive --new-file v2.4.0/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v2.4.0/linux/arch/alpha/kernel/signal.c	Sun Sep  3 11:48:33 2000
+++ linux/arch/alpha/kernel/signal.c	Wed Jan 24 15:16:23 2001
@@ -30,7 +30,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int sys_wait4(int, int *, int, struct rusage *);
 asmlinkage void ret_from_sys_call(void);
 asmlinkage int do_signal(sigset_t *, struct pt_regs *,
 			 struct switch_stack *, unsigned long, unsigned long);
diff -u --recursive --new-file v2.4.0/linux/arch/alpha/kernel/sys_cabriolet.c linux/arch/alpha/kernel/sys_cabriolet.c
--- v2.4.0/linux/arch/alpha/kernel/sys_cabriolet.c	Fri Oct 27 10:55:01 2000
+++ linux/arch/alpha/kernel/sys_cabriolet.c	Wed Jan 24 15:16:23 2001
@@ -42,7 +42,7 @@
 cabriolet_update_irq_hw(unsigned int irq, unsigned long mask)
 {
 	int ofs = (irq - 16) / 8;
-	outb(mask >> (16 + ofs*3), 0x804 + ofs);
+	outb(mask >> (16 + ofs * 8), 0x804 + ofs);
 }
 
 static inline void
diff -u --recursive --new-file v2.4.0/linux/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c
--- v2.4.0/linux/arch/arm/kernel/signal.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/kernel/signal.c	Wed Jan 24 15:21:50 2001
@@ -32,8 +32,6 @@
 #define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn))
 #define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn))
 
-asmlinkage int sys_wait4(pid_t pid, unsigned long * stat_addr,
-			 int options, unsigned long *ru);
 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
diff -u --recursive --new-file v2.4.0/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.4.0/linux/arch/i386/Makefile	Fri Dec 29 14:07:19 2000
+++ linux/arch/i386/Makefile	Wed Jan 10 15:06:14 2001
@@ -50,7 +50,7 @@
 CFLAGS += -march=i686
 endif
 
-ifdef CONFIG_M686FXSR
+ifdef CONFIG_MPENTIUMIII
 CFLAGS += -march=i686
 endif
 
diff -u --recursive --new-file v2.4.0/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.4.0/linux/arch/i386/config.in	Fri Dec 29 14:35:47 2000
+++ linux/arch/i386/config.in	Mon Jan  8 13:27:56 2001
@@ -33,7 +33,7 @@
 	 Pentium-Classic		CONFIG_M586TSC \
 	 Pentium-MMX			CONFIG_M586MMX \
 	 Pentium-Pro/Celeron/Pentium-II	CONFIG_M686 \
-	 Pentium-III			CONFIG_M686FXSR \
+	 Pentium-III			CONFIG_MPENTIUMIII \
 	 Pentium-4			CONFIG_MPENTIUM4 \
 	 K6/K6-II/K6-III		CONFIG_MK6 \
 	 Athlon/K7			CONFIG_MK7 \
@@ -45,8 +45,6 @@
 # Define implied options from the CPU selection here
 #
 
-unset CONFIG_X86_FXSR
-
 if [ "$CONFIG_M386" = "y" ]; then
    define_bool CONFIG_X86_CMPXCHG n
    define_int  CONFIG_X86_L1_CACHE_SHIFT 4
@@ -87,14 +85,12 @@
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
 fi
-if [ "$CONFIG_M686FXSR" = "y" ]; then
+if [ "$CONFIG_MPENTIUMIII" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
    define_bool CONFIG_X86_TSC y
    define_bool CONFIG_X86_GOOD_APIC y
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
-   define_bool CONFIG_X86_FXSR y
-   define_bool CONFIG_X86_XMM y
 fi
 if [ "$CONFIG_MPENTIUM4" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 7
@@ -102,8 +98,6 @@
    define_bool CONFIG_X86_GOOD_APIC y
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
-   define_bool CONFIG_X86_FXSR y
-   define_bool CONFIG_X86_XMM y
 fi
 if [ "$CONFIG_MK6" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
@@ -158,9 +152,7 @@
    define_bool CONFIG_X86_PAE y
 fi
 
-if [ "$CONFIG_X86_FXSR" != "y" ]; then
-   bool 'Math emulation' CONFIG_MATH_EMULATION
-fi
+bool 'Math emulation' CONFIG_MATH_EMULATION
 bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
 bool 'Symmetric multi-processing support' CONFIG_SMP
 if [ "$CONFIG_SMP" != "y" ]; then
diff -u --recursive --new-file v2.4.0/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.4.0/linux/arch/i386/defconfig	Sun Dec 31 09:17:18 2000
+++ linux/arch/i386/defconfig	Fri Jan 19 13:45:22 2001
@@ -27,7 +27,7 @@
 # CONFIG_M586TSC is not set
 # CONFIG_M586MMX is not set
 # CONFIG_M686 is not set
-CONFIG_M686FXSR=y
+CONFIG_MPENTIUMIII=y
 # CONFIG_MPENTIUM4 is not set
 # CONFIG_MK6 is not set
 # CONFIG_MK7 is not set
@@ -45,8 +45,6 @@
 CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_PGE=y
 CONFIG_X86_USE_PPRO_CHECKSUM=y
-CONFIG_X86_FXSR=y
-CONFIG_X86_XMM=y
 # CONFIG_TOSHIBA is not set
 # CONFIG_MICROCODE is not set
 # CONFIG_X86_MSR is not set
@@ -54,6 +52,7 @@
 CONFIG_NOHIGHMEM=y
 # CONFIG_HIGHMEM4G is not set
 # CONFIG_HIGHMEM64G is not set
+# CONFIG_MATH_EMULATION is not set
 # CONFIG_MTRR is not set
 CONFIG_SMP=y
 CONFIG_HAVE_DEC_LOCK=y
@@ -512,11 +511,18 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
+CONFIG_AGP=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_I810=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_ALI=y
 CONFIG_DRM=y
 CONFIG_DRM_TDFX=y
 # CONFIG_DRM_GAMMA is not set
 # CONFIG_DRM_R128 is not set
+CONFIG_DRM_RADEON=y
 # CONFIG_DRM_I810 is not set
 # CONFIG_DRM_MGA is not set
 CONFIG_PCMCIA_SERIAL=y
@@ -538,6 +544,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 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
diff -u --recursive --new-file v2.4.0/linux/arch/i386/kernel/i387.c linux/arch/i386/kernel/i387.c
--- v2.4.0/linux/arch/i386/kernel/i387.c	Fri Nov  3 09:47:48 2000
+++ linux/arch/i386/kernel/i387.c	Thu Jan 11 17:12:18 2001
@@ -18,14 +18,6 @@
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
-#if defined(CONFIG_X86_FXSR)
-#define HAVE_FXSR 1
-#elif defined(CONFIG_X86_RUNTIME_FXSR)
-#define HAVE_FXSR (cpu_has_fxsr)
-#else
-#define HAVE_FXSR 0
-#endif
-
 #ifdef CONFIG_MATH_EMULATION
 #define HAVE_HWFP (boot_cpu_data.hard_math)
 #else
@@ -35,13 +27,13 @@
 /*
  * The _current_ task is using the FPU for the first time
  * so initialize it and set the mxcsr to its default
- * value at reset if we support FXSR and then
+ * value at reset if we support XMM instructions and then
  * remeber the current task has used the FPU.
  */
 void init_fpu(void)
 {
 	__asm__("fninit");
-	if ( HAVE_FXSR )
+	if ( cpu_has_xmm )
 		load_mxcsr(0x1f80);
 		
 	current->used_math = 1;
@@ -51,9 +43,9 @@
  * FPU lazy state save handling.
  */
 
-void save_init_fpu( struct task_struct *tsk )
+static inline void __save_init_fpu( struct task_struct *tsk )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		asm volatile( "fxsave %0 ; fnclex"
 			      : "=m" (tsk->thread.i387.fxsave) );
 	} else {
@@ -61,12 +53,28 @@
 			      : "=m" (tsk->thread.i387.fsave) );
 	}
 	tsk->flags &= ~PF_USEDFPU;
+}
+
+void save_init_fpu( struct task_struct *tsk )
+{
+	__save_init_fpu(tsk);
 	stts();
 }
 
+void kernel_fpu_begin(void)
+{
+	struct task_struct *tsk = current;
+
+	if (tsk->flags & PF_USEDFPU) {
+		__save_init_fpu(tsk);
+		return;
+	}
+	clts();
+}
+
 void restore_fpu( struct task_struct *tsk )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		asm volatile( "fxrstor %0"
 			      : : "m" (tsk->thread.i387.fxsave) );
 	} else {
@@ -144,7 +152,7 @@
 
 unsigned short get_fpu_cwd( struct task_struct *tsk )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		return tsk->thread.i387.fxsave.cwd;
 	} else {
 		return (unsigned short)tsk->thread.i387.fsave.cwd;
@@ -153,7 +161,7 @@
 
 unsigned short get_fpu_swd( struct task_struct *tsk )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		return tsk->thread.i387.fxsave.swd;
 	} else {
 		return (unsigned short)tsk->thread.i387.fsave.swd;
@@ -162,7 +170,7 @@
 
 unsigned short get_fpu_twd( struct task_struct *tsk )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		return tsk->thread.i387.fxsave.twd;
 	} else {
 		return (unsigned short)tsk->thread.i387.fsave.twd;
@@ -171,7 +179,7 @@
 
 unsigned short get_fpu_mxcsr( struct task_struct *tsk )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		return tsk->thread.i387.fxsave.mxcsr;
 	} else {
 		return 0x1f80;
@@ -180,7 +188,7 @@
 
 void set_fpu_cwd( struct task_struct *tsk, unsigned short cwd )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		tsk->thread.i387.fxsave.cwd = cwd;
 	} else {
 		tsk->thread.i387.fsave.cwd = ((long)cwd | 0xffff0000);
@@ -189,7 +197,7 @@
 
 void set_fpu_swd( struct task_struct *tsk, unsigned short swd )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		tsk->thread.i387.fxsave.swd = swd;
 	} else {
 		tsk->thread.i387.fsave.swd = ((long)swd | 0xffff0000);
@@ -198,7 +206,7 @@
 
 void set_fpu_twd( struct task_struct *tsk, unsigned short twd )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		tsk->thread.i387.fxsave.twd = twd_i387_to_fxsr(twd);
 	} else {
 		tsk->thread.i387.fsave.twd = ((long)twd | 0xffff0000);
@@ -207,7 +215,7 @@
 
 void set_fpu_mxcsr( struct task_struct *tsk, unsigned short mxcsr )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_xmm ) {
 		tsk->thread.i387.fxsave.mxcsr = mxcsr;
 	}
 }
@@ -321,7 +329,7 @@
 	current->used_math = 0;
 
 	if ( HAVE_HWFP ) {
-		if ( HAVE_FXSR ) {
+		if ( cpu_has_fxsr ) {
 			return save_i387_fxsave( buf );
 		} else {
 			return save_i387_fsave( buf );
@@ -354,7 +362,7 @@
 	int err;
 
 	if ( HAVE_HWFP ) {
-		if ( HAVE_FXSR ) {
+		if ( cpu_has_fxsr ) {
 			err =  restore_i387_fxsave( buf );
 		} else {
 			err = restore_i387_fsave( buf );
@@ -387,7 +395,7 @@
 int get_fpregs( struct user_i387_struct *buf, struct task_struct *tsk )
 {
 	if ( HAVE_HWFP ) {
-		if ( HAVE_FXSR ) {
+		if ( cpu_has_fxsr ) {
 			return get_fpregs_fxsave( buf, tsk );
 		} else {
 			return get_fpregs_fsave( buf, tsk );
@@ -415,7 +423,7 @@
 int set_fpregs( struct task_struct *tsk, struct user_i387_struct *buf )
 {
 	if ( HAVE_HWFP ) {
-		if ( HAVE_FXSR ) {
+		if ( cpu_has_fxsr ) {
 			return set_fpregs_fxsave( tsk, buf );
 		} else {
 			return set_fpregs_fsave( tsk, buf );
@@ -428,9 +436,10 @@
 
 int get_fpxregs( struct user_fxsr_struct *buf, struct task_struct *tsk )
 {
-	if ( HAVE_FXSR ) {
-		__copy_to_user( (void *)buf, &tsk->thread.i387.fxsave,
-				sizeof(struct user_fxsr_struct) );
+	if ( cpu_has_fxsr ) {
+		if (__copy_to_user( (void *)buf, &tsk->thread.i387.fxsave,
+				    sizeof(struct user_fxsr_struct) ))
+			return -EFAULT;
 		return 0;
 	} else {
 		return -EIO;
@@ -439,7 +448,7 @@
 
 int set_fpxregs( struct task_struct *tsk, struct user_fxsr_struct *buf )
 {
-	if ( HAVE_FXSR ) {
+	if ( cpu_has_fxsr ) {
 		__copy_from_user( &tsk->thread.i387.fxsave, (void *)buf,
 				  sizeof(struct user_fxsr_struct) );
 		/* mxcsr bit 6 and 31-16 must be zero for security reasons */
@@ -485,7 +494,7 @@
 	fpvalid = tsk->used_math;
 	if ( fpvalid ) {
 		unlazy_fpu( tsk );
-		if ( HAVE_FXSR ) {
+		if ( cpu_has_fxsr ) {
 			copy_fpu_fxsave( tsk, fpu );
 		} else {
 			copy_fpu_fsave( tsk, fpu );
@@ -500,7 +509,7 @@
 	int fpvalid;
 	struct task_struct *tsk = current;
 
-	fpvalid = tsk->used_math && HAVE_FXSR;
+	fpvalid = tsk->used_math && cpu_has_fxsr;
 	if ( fpvalid ) {
 		unlazy_fpu( tsk );
 		memcpy( fpu, &tsk->thread.i387.fxsave,
diff -u --recursive --new-file v2.4.0/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.4.0/linux/arch/i386/kernel/io_apic.c	Sun Oct  1 20:35:15 2000
+++ linux/arch/i386/kernel/io_apic.c	Sun Jan 21 15:41:47 2001
@@ -253,7 +253,8 @@
  * Find a specific PCI IRQ entry.
  * Not an __init, possibly needed by modules
  */
-static int __init pin_2_irq(int idx, int apic, int pin);
+static int pin_2_irq(int idx, int apic, int pin);
+
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
 {
 	int apic, i, best_guess = -1;
@@ -475,7 +476,7 @@
 	return MPBIOS_trigger(idx);
 }
 
-static int __init pin_2_irq(int idx, int apic, int pin)
+static int pin_2_irq(int idx, int apic, int pin)
 {
 	int irq, i;
 	int bus = mp_irqs[idx].mpc_srcbus;
diff -u --recursive --new-file v2.4.0/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c
--- v2.4.0/linux/arch/i386/kernel/pci-irq.c	Wed Jan  3 20:45:26 2001
+++ linux/arch/i386/kernel/pci-irq.c	Mon Jan 29 12:10:04 2001
@@ -234,22 +234,107 @@
 	return 1;
 }
 
+/*
+ *	PIRQ routing for SiS 85C503 router used in several SiS chipsets
+ *	According to the SiS 5595 datasheet (preliminary V1.0, 12/24/1997)
+ *	the related registers work as follows:
+ *	
+ *	general: one byte per re-routable IRQ,
+ *		 bit 7      IRQ mapping enabled (0) or disabled (1)
+ *		 bits [6:4] reserved
+ *		 bits [3:0] IRQ to map to
+ *		     allowed: 3-7, 9-12, 14-15
+ *		     reserved: 0, 1, 2, 8, 13
+ *
+ *	individual registers in device config space:
+ *
+ *	0x41/0x42/0x43/0x44:	PCI INT A/B/C/D - bits as in general case
+ *
+ *	0x61:			IDEIRQ: bits as in general case - but:
+ *				bits [6:5] must be written 01
+ *				bit 4 channel-select primary (0), secondary (1)
+ *
+ *	0x62:			USBIRQ: bits as in general case - but:
+ *				bit 4 OHCI function disabled (0), enabled (1)
+ *	
+ *	0x6a:			ACPI/SCI IRQ - bits as in general case
+ *
+ *	0x7e:			Data Acq. Module IRQ - bits as in general case
+ *
+ *	Apparently there are systems implementing PCI routing table using both
+ *	link values 0x01-0x04 and 0x41-0x44 for PCI INTA..D, but register offsets
+ *	like 0x62 as link values for USBIRQ e.g. So there is no simple
+ *	"register = offset + pirq" relation.
+ *	Currently we support PCI INTA..D and USBIRQ and try our best to handle
+ *	both link mappings.
+ *	IDE/ACPI/DAQ mapping is currently unsupported (left untouched as set by BIOS).
+ */
+
 static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
 	u8 x;
-	int reg = 0x41 + (pirq - 'A') ;
+	int reg = pirq;
 
-	pci_read_config_byte(router, reg, &x);
+	switch(pirq) {
+		case 0x01:
+		case 0x02:
+		case 0x03:
+		case 0x04:
+			reg += 0x40;
+		case 0x41:
+		case 0x42:
+		case 0x43:
+		case 0x44:
+		case 0x62:
+			pci_read_config_byte(router, reg, &x);
+			if (reg != 0x62)
+				break;
+			if (!(x & 0x40))
+				return 0;
+			break;
+		case 0x61:
+		case 0x6a:
+		case 0x7e:
+			printk("SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n");
+			return 0;
+		default:			
+			printk("SiS router pirq escape (%d)\n", pirq);
+			return 0;
+	}
 	return (x & 0x80) ? 0 : (x & 0x0f);
 }
 
 static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
 	u8 x;
-	int reg = 0x41 + (pirq - 'A') ;
+	int reg = pirq;
 
-	pci_read_config_byte(router, reg, &x);
-	x = (pirq & 0x20) ? 0 : (irq & 0x0f);
+	switch(pirq) {
+		case 0x01:
+		case 0x02:
+		case 0x03:
+		case 0x04:
+			reg += 0x40;
+		case 0x41:
+		case 0x42:
+		case 0x43:
+		case 0x44:
+		case 0x62:
+			x = (irq&0x0f) ? (irq&0x0f) : 0x80;
+			if (reg != 0x62)
+				break;
+			/* always mark OHCI enabled, as nothing else knows about this */
+			x |= 0x40;
+			break;
+		case 0x61:
+		case 0x6a:
+		case 0x7e:
+			printk("advanced SiS pirq mapping not yet implemented\n");
+			return 0;
+		default:			
+			printk("SiS router pirq escape (%d)\n", pirq);
+			return 0;
+	}
 	pci_write_config_byte(router, reg, x);
 
 	return 1;
@@ -462,18 +547,9 @@
 		irq = pirq & 0xf;
 		DBG(" -> hardcoded IRQ %d\n", irq);
 		msg = "Hardcoded";
-		if (dev->irq && dev->irq != irq) {
-			printk("IRQ routing conflict in pirq table! Try 'pci=autoirq'\n");
-			return 0;
-		}
 	} else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq))) {
 		DBG(" -> got IRQ %d\n", irq);
 		msg = "Found";
-		/* We refuse to override the dev->irq information. Give a warning! */
-	    	if (dev->irq && dev->irq != irq) {
-	    		printk("IRQ routing conflict in pirq table! Try 'pci=autoirq'\n");
-	    		return 0;
-	    	}
 	} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
 		DBG(" -> assigning IRQ %d", newirq);
 		if (r->set(pirq_router_dev, dev, pirq, newirq)) {
@@ -504,6 +580,11 @@
 		if (!info)
 			continue;
 		if (info->irq[pin].link == pirq) {
+			/* We refuse to override the dev->irq information. Give a warning! */
+		    	if (dev2->irq && dev2->irq != irq) {
+		    		printk("IRQ routing conflict in pirq table for device %s\n", dev2->slot_name);
+		    		continue;
+		    	}
 			dev2->irq = irq;
 			pirq_penalty[irq]++;
 			if (dev != dev2)
diff -u --recursive --new-file v2.4.0/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.4.0/linux/arch/i386/kernel/setup.c	Sun Dec 31 10:26:18 2000
+++ linux/arch/i386/kernel/setup.c	Sun Jan 28 19:01:13 2001
@@ -147,6 +147,7 @@
 extern unsigned long cpu_khz;
 
 static int disable_x86_serial_nr __initdata = 1;
+static int disable_x86_fxsr __initdata = 0;
 
 /*
  * This is set up by the setup-routine at boot-time
@@ -518,7 +519,7 @@
 
 		e820.nr_map = 0;
 		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
-		add_memory_region(HIGH_MEMORY, (mem_size << 10) - HIGH_MEMORY, E820_RAM);
+		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
   	}
 	printk("BIOS-provided physical RAM map:\n");
 	print_memory_map(who);
@@ -1400,9 +1401,6 @@
 					wrmsr (0x1107, lo, hi);
 
 					set_bit(X86_FEATURE_CX8, &c->x86_capability);
-					rdmsr (0x80000001, lo, hi);
-					if (hi & (1<<31))
-						set_bit(X86_FEATURE_3DNOW, &c->x86_capability);
 
 					get_model_name(c);
 					display_cacheinfo(c);
@@ -1796,6 +1794,13 @@
 }
 __setup("serialnumber", x86_serial_nr_setup);
 
+int __init x86_fxsr_setup(char * s)
+{
+	disable_x86_fxsr = 1;
+	return 1;
+}
+__setup("nofxsr", x86_fxsr_setup);
+
 
 /* Standard macro to see if a specific flag is changeable */
 static inline int flag_is_changeable_p(u32 flag)
@@ -1866,7 +1871,8 @@
 	/* Detect Cyrix with disabled CPUID */
 	if ( c->x86 == 4 && test_cyrix_52div() ) {
 		strcpy(c->x86_vendor_id, "CyrixInstead");
-	}
+	        c->x86_vendor = X86_VENDOR_CYRIX;
+	} else
 
 	/* Detect NexGen with old hypercode */
 	if ( deep_magic_nexgen_probe() ) {
@@ -2000,10 +2006,16 @@
 	 */
 
 	/* TSC disabled? */
-#ifdef CONFIG_TSC
+#ifndef CONFIG_X86_TSC
 	if ( tsc_disable )
 		clear_bit(X86_FEATURE_TSC, &c->x86_capability);
 #endif
+
+	/* FXSR disabled? */
+	if (disable_x86_fxsr) {
+		clear_bit(X86_FEATURE_FXSR, &c->x86_capability);
+		clear_bit(X86_FEATURE_XMM, &c->x86_capability);
+	}
 
 	/* Disable the PN if appropriate */
 	squash_the_stupid_serial_number(c);
diff -u --recursive --new-file v2.4.0/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.4.0/linux/arch/i386/kernel/signal.c	Mon Sep 25 13:10:28 2000
+++ linux/arch/i386/kernel/signal.c	Mon Jan 22 15:42:57 2001
@@ -26,8 +26,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-			 int options, unsigned long *ru);
 asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
diff -u --recursive --new-file v2.4.0/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.4.0/linux/arch/i386/kernel/traps.c	Wed Jan  3 20:45:26 2001
+++ linux/arch/i386/kernel/traps.c	Mon Jan 15 16:54:20 2001
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <linux/highmem.h>
 
 #ifdef CONFIG_MCA
 #include <linux/mca.h>
diff -u --recursive --new-file v2.4.0/linux/arch/i386/lib/mmx.c linux/arch/i386/lib/mmx.c
--- v2.4.0/linux/arch/i386/lib/mmx.c	Wed Nov  8 17:09:49 2000
+++ linux/arch/i386/lib/mmx.c	Thu Jan 11 17:42:24 2001
@@ -2,6 +2,8 @@
 #include <linux/string.h>
 #include <linux/sched.h>
 
+#include <asm/i387.h>
+
 /*
  *	MMX 3DNow! library helper functions
  *
@@ -26,13 +28,7 @@
 	void *p=to;
 	int i= len >> 6;	/* len/64 */
 
-	if (!(current->flags & PF_USEDFPU))
-		clts();
-	else
-	{
-		__asm__ __volatile__ ( " fnsave %0; fwait\n"::"m"(current->thread.i387));
-		current->flags &= ~PF_USEDFPU;
-	}
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 		"1: prefetch (%0)\n"		/* This set is 28 bytes */
@@ -88,20 +84,15 @@
 	 *	Now do the tail of the block
 	 */
 	__memcpy(to, from, len&63);
-	stts();
+	kernel_fpu_end();
 	return p;
 }
 
 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;
-	}
+
+	kernel_fpu_begin();
 	
 	__asm__ __volatile__ (
 		"  pxor %%mm0, %%mm0\n" : :
@@ -127,19 +118,14 @@
 	__asm__ __volatile__ (
 		"  sfence \n" : :
 	);
-	stts();
+	kernel_fpu_end();
 }
 
 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;
-	}
+
+	kernel_fpu_begin();
 
 	/* maybe the prefetch stuff can go before the expensive fnsave...
 	 * but that is for later. -AV
@@ -199,7 +185,7 @@
 	__asm__ __volatile__ (
 		"  sfence \n" : :
 	);
-	stts();
+	kernel_fpu_end();
 }
 
 /*
diff -u --recursive --new-file v2.4.0/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.4.0/linux/arch/i386/mm/init.c	Tue Nov 28 22:43:39 2000
+++ linux/arch/i386/mm/init.c	Mon Jan 15 11:06:55 2001
@@ -317,7 +317,7 @@
 	pgd_t *pgd, *pgd_base;
 	int i, j, k;
 	pmd_t *pmd;
-	pte_t *pte;
+	pte_t *pte, *pte_base;
 
 	/*
 	 * This can be zero as well - no problem, in that case we exit
@@ -366,11 +366,7 @@
 				continue;
 			}
 
-			pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-			set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)));
-
-			if (pte != pte_offset(pmd, 0))
-				BUG();
+			pte_base = pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
 
 			for (k = 0; k < PTRS_PER_PTE; pte++, k++) {
 				vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE;
@@ -378,6 +374,10 @@
 					break;
 				*pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL);
 			}
+			set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte_base)));
+			if (pte_base != pte_offset(pmd, 0))
+				BUG();
+
 		}
 	}
 
diff -u --recursive --new-file v2.4.0/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c
--- v2.4.0/linux/arch/ia64/ia32/sys_ia32.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/ia32/sys_ia32.c	Wed Jan 24 15:22:26 2001
@@ -1957,9 +1957,6 @@
 	return err;
 }
 
-extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr,
-				int options, struct rusage * ru);
-
 asmlinkage long
 sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options,
 	    struct rusage32 *ru)
diff -u --recursive --new-file v2.4.0/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c
--- v2.4.0/linux/arch/m68k/kernel/signal.c	Mon Nov 27 18:02:06 2000
+++ linux/arch/m68k/kernel/signal.c	Wed Jan 24 15:21:28 2001
@@ -47,8 +47,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-			 int options, unsigned long *ru);
 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 
 const int frame_extra_sizes[16] = {
diff -u --recursive --new-file v2.4.0/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c
--- v2.4.0/linux/arch/mips/kernel/irixsig.c	Sun Sep  3 11:50:03 2000
+++ linux/arch/mips/kernel/irixsig.c	Wed Jan 24 15:21:10 2001
@@ -16,8 +16,6 @@
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-                         int options, unsigned long *ru);
 extern asmlinkage void syscall_trace(void);
 
 #undef DEBUG_SIG
diff -u --recursive --new-file v2.4.0/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c
--- v2.4.0/linux/arch/mips/kernel/signal.c	Sun Sep  3 11:49:09 2000
+++ linux/arch/mips/kernel/signal.c	Wed Jan 24 15:20:59 2001
@@ -30,8 +30,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-extern asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-                         int options, unsigned long *ru);
 extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 extern asmlinkage int save_fp_context(struct sigcontext *sc);
 extern asmlinkage int restore_fp_context(struct sigcontext *sc);
diff -u --recursive --new-file v2.4.0/linux/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c
--- v2.4.0/linux/arch/mips64/kernel/linux32.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/kernel/linux32.c	Wed Jan 24 15:22:38 2001
@@ -585,9 +585,6 @@
 	return err;
 }
 
-extern asmlinkage int sys_wait4(pid_t pid, unsigned int * stat_addr,
-				int options, struct rusage * ru);
-
 asmlinkage int
 sys32_wait4(__kernel_pid_t32 pid, unsigned int * stat_addr, int options,
 	    struct rusage32 * ru)
diff -u --recursive --new-file v2.4.0/linux/arch/mips64/kernel/signal.c linux/arch/mips64/kernel/signal.c
--- v2.4.0/linux/arch/mips64/kernel/signal.c	Sun Sep  3 11:53:42 2000
+++ linux/arch/mips64/kernel/signal.c	Wed Jan 24 15:22:55 2001
@@ -31,8 +31,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-extern asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-                         int options, unsigned long *ru);
 extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 extern asmlinkage int save_fp_context(struct sigcontext *sc);
 extern asmlinkage int restore_fp_context(struct sigcontext *sc);
diff -u --recursive --new-file v2.4.0/linux/arch/mips64/kernel/signal32.c linux/arch/mips64/kernel/signal32.c
--- v2.4.0/linux/arch/mips64/kernel/signal32.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/kernel/signal32.c	Wed Jan 24 15:22:55 2001
@@ -30,8 +30,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-extern asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-                         int options, unsigned long *ru);
 extern asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs);
 extern asmlinkage int save_fp_context(struct sigcontext *sc);
 extern asmlinkage int restore_fp_context(struct sigcontext *sc);
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/8260_io/enet.c linux/arch/ppc/8260_io/enet.c
--- v2.4.0/linux/arch/ppc/8260_io/enet.c	Sun Sep 17 09:48:05 2000
+++ linux/arch/ppc/8260_io/enet.c	Mon Jan 22 15:41:14 2001
@@ -633,6 +633,9 @@
 	/* Allocate some private information.
 	*/
 	cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
+	if (cep == NULL)
+		return -ENOMEM;
+
 	__clear_user(cep,sizeof(*cep));
 	spin_lock_init(&cep->lock);
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/8260_io/fcc_enet.c linux/arch/ppc/8260_io/fcc_enet.c
--- v2.4.0/linux/arch/ppc/8260_io/fcc_enet.c	Tue Sep 19 08:31:53 2000
+++ linux/arch/ppc/8260_io/fcc_enet.c	Mon Jan 22 15:41:14 2001
@@ -1082,6 +1082,9 @@
 		*/
 		cep = (struct fcc_enet_private *)
 					kmalloc(sizeof(*cep), GFP_KERNEL);
+		if (cep == NULL)
+			return -ENOMEM;
+
 		__clear_user(cep,sizeof(*cep));
 		spin_lock_init(&cep->lock);
 		cep->fip = fip;
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.4.0/linux/arch/ppc/8xx_io/enet.c	Sun Sep 17 09:48:05 2000
+++ linux/arch/ppc/8xx_io/enet.c	Mon Jan 22 15:41:14 2001
@@ -652,7 +652,9 @@
 	/* Allocate some private information.
 	*/
 	cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
-	/*memset(cep, 0, sizeof(*cep));*/
+	if (cep == NULL)
+		return -ENOMEM;
+
 	__clear_user(cep,sizeof(*cep));
 	spin_lock_init(&cep->lock);
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c
--- v2.4.0/linux/arch/ppc/8xx_io/fec.c	Wed Dec  6 12:06:18 2000
+++ linux/arch/ppc/8xx_io/fec.c	Mon Jan 22 15:41:14 2001
@@ -1459,6 +1459,9 @@
 	/* Allocate some private information.
 	*/
 	fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL);
+	if (fep == NULL)
+		return -ENOMEM;
+
 	__clear_user(fep,sizeof(*fep));
 
 	/* Create an Ethernet device instance.
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.4.0/linux/arch/ppc/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/ppc/Makefile	Mon Jan 22 15:41:14 2001
@@ -145,9 +145,6 @@
 clean_config:
 	rm -f .config arch/ppc/defconfig
 
-gemini_config: clean_config
-	cp -f arch/ppc/configs/gemini_defconfig arch/ppc/defconfig
-
 pmac_config: clean_config
 	cp -f arch/ppc/configs/pmac_defconfig arch/ppc/defconfig
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.4.0/linux/arch/ppc/boot/Makefile	Mon Jun 19 17:59:35 2000
+++ linux/arch/ppc/boot/Makefile	Mon Jan 22 15:41:14 2001
@@ -25,22 +25,12 @@
 IOFF = 0
 ISZ = 0
 
-ifeq ($(CONFIG_ALL_PPC),y)
-CONFIG_PREP=y
-endif
-
 ifeq ($(CONFIG_SMP),y)
 TFTPIMAGE=/tftpboot/zImage.prep.smp$(MSIZE)
 else
 TFTPIMAGE=/tftpboot/zImage.prep$(MSIZE)
 endif
 
-ifeq ($(CONFIG_SMP),y)
-TFTPSIMAGE=/tftpboot/sImage.smp
-else
-TFTPSIMAGE=/tftpboot/sImage
-endif
-
 ifeq ($(CONFIG_PPC64BRIDGE),y)
 MSIZE=.64
 else
@@ -81,8 +71,8 @@
 		zvmlinux.initrd.tmp $@
 	rm zvmlinux.initrd.tmp
 
-zImage: zvmlinux mkprep sImage
-ifdef CONFIG_PREP
+zImage: zvmlinux mkprep
+ifdef CONFIG_ALL_PPC
 	./mkprep -pbp zvmlinux zImage
 endif
 ifdef CONFIG_APUS
@@ -90,13 +80,8 @@
 	gzip $(GZIP_FLAGS) vmapus
 endif
 
-sImage: ../../../vmlinux
-ifdef CONFIG_GEMINI
-	$(OBJCOPY) -I elf32-powerpc -O binary ../../../vmlinux sImage
-endif
-
 zImage.initrd: zvmlinux.initrd mkprep
-ifdef CONFIG_PREP
+ifdef CONFIG_ALL_PPC
 	./mkprep -pbp zvmlinux.initrd zImage.initrd
 endif
 
@@ -128,18 +113,15 @@
 	$(HOSTCC) -o mkprep mkprep.c
 
 znetboot : zImage
-ifdef CONFIG_PREP
+ifdef CONFIG_ALL_PPC
 	cp zImage $(TFTPIMAGE)
 endif
-ifdef CONFIG_GEMINI
-	cp sImage $(TFTPSIMAGE)
-endif
 
 znetboot.initrd : zImage.initrd
 	cp zImage.initrd $(TFTPIMAGE)
 
 clean:
-	rm -f vmlinux* zvmlinux* mkprep zImage* sImage*
+	rm -f vmlinux* zvmlinux* mkprep zImage*
 
 fastdep:
 	$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/boot/vreset.c linux/arch/ppc/boot/vreset.c
--- v2.4.0/linux/arch/ppc/boot/vreset.c	Thu May 21 14:24:05 1998
+++ linux/arch/ppc/boot/vreset.c	Mon Jan 22 15:41:14 2001
@@ -19,12 +19,16 @@
  */
 
 #include "iso_font.h"
-#include <linux/delay.h>
 
 extern char *vidmem;
 extern int lines, cols;
-/* estimate for delay */
-unsigned long loops_per_sec = 50000000;;
+
+static void mdelay(int ms)
+{
+	for (; ms > 0; --ms)
+		udelay(1000);
+}
+
 /*
  * VGA Register  
  */
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile
--- v2.4.0/linux/arch/ppc/chrpboot/Makefile	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/chrpboot/Makefile	Mon Jan 22 15:41:14 2001
@@ -23,11 +23,6 @@
 OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o
 LIBS = $(TOPDIR)/lib/lib.a
 
-ifeq ($(CONFIG_ALL_PPC),y)
-# yes, we want to build chrp stuff
-CONFIG_CHRP = y
-endif
-
 ifeq ($(CONFIG_SMP),y)
 TFTPIMAGE=/tftpboot/zImage.chrp.smp$(MSIZE)
 else
@@ -37,10 +32,10 @@
 all:	$(TOPDIR)/zImage
 
 #
-# Only build anything here if we're configured for CHRP
+# Only build anything here if we're configured for ALL_PPC
 # -- cort
 #
-ifeq ($(CONFIG_CHRP),y)
+ifeq ($(CONFIG_ALL_PPC),y)
 znetboot: zImage
 	cp zImage $(TFTPIMAGE)
 
@@ -96,6 +91,7 @@
 
 clean:
 	rm -f piggyback note addnote $(OBJS) zImage
+	rm -f zImage.rs6k zImage.initrd zImage.initrd.rs6k
 
 fastdep:
 	$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile
--- v2.4.0/linux/arch/ppc/coffboot/Makefile	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/coffboot/Makefile	Mon Jan 22 15:41:14 2001
@@ -20,18 +20,13 @@
 MSIZE=
 endif
 
-ifeq ($(CONFIG_ALL_PPC),y)
-# yes, we want to build pmac stuff
-CONFIG_PMAC = y
-endif
-
 ifeq ($(CONFIG_SMP),y)
 TFTPIMAGE=/tftpboot/zImage.pmac.smp$(MSIZE)
 else
 TFTPIMAGE=/tftpboot/zImage.pmac$(MSIZE)
 endif
 
-ifeq ($(CONFIG_PMAC),y)
+ifeq ($(CONFIG_ALL_PPC),y)
 chrpmain.o: chrpmain.c
 	$(CC) $(CFLAGS) -DSYSMAP_OFFSET=0 -DSYSMAP_SIZE=0 -c chrpmain.c
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/coffboot/coffmain.c linux/arch/ppc/coffboot/coffmain.c
--- v2.4.0/linux/arch/ppc/coffboot/coffmain.c	Sat Jan  8 12:59:39 2000
+++ linux/arch/ppc/coffboot/coffmain.c	Mon Jan 22 15:41:14 2001
@@ -22,11 +22,18 @@
 #define get_32be(x)	(*(unsigned *)(x))
 
 #define RAM_START	0xc0000000
-#define PROG_START	RAM_START
 #define RAM_END		(RAM_START + 0x800000)	/* only 8M mapped with BATs */
 
+#define PROG_START	RAM_START
+#define PROG_SIZE	0x00400000
+
+#define SCRATCH_SIZE	(128 << 10)
+
 char *avail_ram;
-char *end_avail;
+char *begin_avail, *end_avail;
+char *avail_high;
+unsigned int heap_use;
+unsigned int heap_max;
 
 extern char _start[], _end[];
 extern char image_data[];
@@ -34,6 +41,7 @@
 extern char initrd_data[];
 extern int initrd_len;
 
+char heap[SCRATCH_SIZE];
 
 boot(int a1, int a2, void *prom)
 {
@@ -58,16 +66,18 @@
     im = image_data;
     len = image_len;
     /* claim 3MB starting at 0 */
-    claim(0, 3 << 20, 0);
+    claim(0, PROG_SIZE, 0);
     dst = (void *) RAM_START;
     if (im[0] == 0x1f && im[1] == 0x8b) {
-	/* claim 512kB for scratch space */
-	avail_ram = claim(0, 512 << 10, 0x10) + RAM_START;
-	end_avail = avail_ram + (512 << 10);
-	printf("avail_ram = %x\n", avail_ram);
+	/* claim some memory for scratch space */
+	begin_avail = avail_high = avail_ram = heap;
+	end_avail = heap + sizeof(heap);
+	printf("heap at 0x%x\n", avail_ram);
 	printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
-	gunzip(dst, 3 << 20, im, &len);
+	gunzip(dst, PROG_SIZE, im, &len);
 	printf("done %u bytes\n", len);
+	printf("%u bytes of heap consumed, max in use %u\n",
+	       avail_high - begin_avail, heap_max);
     } else {
 	memmove(dst, im, len);
     }
@@ -78,9 +88,6 @@
     sa = (unsigned long)PROG_START;
     printf("start address = 0x%x\n", sa);
 
-#if 0
-    pause();
-#endif
     (*(void (*)())sa)(a1, a2, prom);
 
     printf("returned?\n");
@@ -114,13 +121,33 @@
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
 }
 
+struct memchunk {
+    unsigned int size;
+    struct memchunk *next;
+};
+
+static struct memchunk *freechunks;
+
 void *zalloc(void *x, unsigned items, unsigned size)
 {
-    void *p = avail_ram;
+    void *p;
+    struct memchunk **mpp, *mp;
 
     size *= items;
     size = (size + 7) & -8;
+    heap_use += size;
+    if (heap_use > heap_max)
+	heap_max = heap_use;
+    for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
+	if (mp->size == size) {
+	    *mpp = mp->next;
+	    return mp;
+	}
+    }
+    p = avail_ram;
     avail_ram += size;
+    if (avail_ram > avail_high)
+	avail_high = avail_ram;
     if (avail_ram > end_avail) {
 	printf("oops... out of memory\n");
 	pause();
@@ -130,6 +157,17 @@
 
 void zfree(void *x, void *addr, unsigned nb)
 {
+    struct memchunk *mp = addr;
+
+    nb = (nb + 7) & -8;
+    heap_use -= nb;
+    if (avail_ram == addr + nb) {
+	avail_ram = addr;
+	return;
+    }
+    mp->size = nb;
+    mp->next = freechunks;
+    freechunks = mp;
 }
 
 #define HEAD_CRC	2
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/coffboot/main.c linux/arch/ppc/coffboot/main.c
--- v2.4.0/linux/arch/ppc/coffboot/main.c	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/coffboot/main.c	Wed Dec 31 16:00:00 1969
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include "nonstdio.h"
-#include "rs6000.h"
-#include "zlib.h"
-#include <asm/bootinfo.h>
-#include <asm/processor.h>
-#define __KERNEL__
-#include <asm/page.h>
-
-extern void *finddevice(const char *);
-extern int getprop(void *, const char *, void *, int);
-void gunzip(void *, int, unsigned char *, int *);
-
-#define get_16be(x)	(*(unsigned short *)(x))
-#define get_32be(x)	(*(unsigned *)(x))
-
-#define RAM_START	0xc0000000
-#define PROG_START	RAM_START
-#define RAM_END		(RAM_START + 0x800000)	/* only 8M mapped with BATs */
-
-#define RAM_FREE	(RAM_START + 0x540000)	/* after image of coffboot */
-
-char *avail_ram;
-char *end_avail;
-
-coffboot(int a1, int a2, void *prom)
-{
-    void *options;
-    unsigned loadbase;
-    struct external_filehdr *eh;
-    struct external_scnhdr *sp;
-    struct external_scnhdr *isect, *rsect;
-    int ns, oh, i;
-    unsigned sa, len;
-    void *dst;
-    unsigned char *im;
-    unsigned initrd_start, initrd_size;
-
-    printf("coffboot starting\n");
-    options = finddevice("/options");
-    if (options == (void *) -1)
-	exit();
-    if (getprop(options, "load-base", &loadbase, sizeof(loadbase))
-	!= sizeof(loadbase)) {
-	printf("error getting load-base\n");
-	exit();
-    }
-    setup_bats(RAM_START);
-
-    loadbase += RAM_START;
-    eh = (struct external_filehdr *) loadbase;
-    ns = get_16be(eh->f_nscns);
-    oh = get_16be(eh->f_opthdr);
-
-    sp = (struct external_scnhdr *) (loadbase + sizeof(struct external_filehdr) + oh);
-    isect = rsect = NULL;
-    for (i = 0; i < ns; ++i, ++sp) {
-	if (strcmp(sp->s_name, "image") == 0)
-	    isect = sp;
-	else if (strcmp(sp->s_name, "initrd") == 0)
-	    rsect = sp;
-    }
-    if (isect == NULL) {
-	printf("image section not found\n");
-	exit();
-    }
-
-    if (rsect != NULL && (initrd_size = get_32be(rsect->s_size)) != 0) {
-	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
-	a1 = initrd_start;
-	a2 = initrd_size;
-	printf("initial ramdisk at %x (%u bytes)\n",
-	       initrd_start, initrd_size);
-	memcpy((char *) initrd_start,
-	       (char *) (loadbase + get_32be(rsect->s_scnptr)),
-	       initrd_size);
-	end_avail = (char *) initrd_start;
-    } else {
-	end_avail = (char *) RAM_END;
-    }
-	
-    im = (unsigned char *)(loadbase + get_32be(isect->s_scnptr));
-    len = get_32be(isect->s_size);
-    dst = (void *) PROG_START;
-
-    if (im[0] == 0x1f && im[1] == 0x8b) {
-	void *cp = (void *) RAM_FREE;
-	avail_ram = (void *) (RAM_FREE + ((len + 7) & -8));
-	memcpy(cp, im, len);
-	printf("gunzipping... ");
-	gunzip(dst, 0x400000, cp, &len);
-	printf("done\n");
-
-    } else {
-	memmove(dst, im, len);
-    }
-
-    flush_cache(dst, len);
-
-    sa = (unsigned long)dst;
-    printf("start address = 0x%x\n", sa);
-
-#if 0
-    pause();
-#endif
-    {
-	    struct bi_record *rec;
-	    
-	    rec = (struct bi_record *)_ALIGN((unsigned long)dst+len+(1<<20)-1,(1<<20));
-	    
-	    rec->tag = BI_FIRST;
-	    rec->size = sizeof(struct bi_record);
-	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	    rec->tag = BI_BOOTLOADER_ID;
-	    sprintf( (char *)rec->data, "coffboot");
-	    rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1;
-	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
-	    rec->tag = BI_MACHTYPE;
-	    rec->data[0] = _MACH_Pmac;
-	    rec->data[1] = 1;
-	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
-	    rec->tag = BI_LAST;
-	    rec->size = sizeof(struct bi_record);
-	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-    }
-    
-    (*(void (*)())sa)(a1, a2, prom);
-
-    printf("returned?\n");
-
-    pause();
-}
-
-void *zalloc(void *x, unsigned items, unsigned size)
-{
-    void *p = avail_ram;
-
-    size *= items;
-    size = (size + 7) & -8;
-    avail_ram += size;
-    if (avail_ram > end_avail) {
-	printf("oops... out of memory\n");
-	pause();
-    }
-    return p;
-}
-
-void zfree(void *x, void *addr, unsigned nb)
-{
-}
-
-#define HEAD_CRC	2
-#define EXTRA_FIELD	4
-#define ORIG_NAME	8
-#define COMMENT		0x10
-#define RESERVED	0xe0
-
-#define DEFLATED	8
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
-    z_stream s;
-    int r, i, flags;
-
-    /* skip header */
-    i = 10;
-    flags = src[3];
-    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-	printf("bad gzipped data\n");
-	exit();
-    }
-    if ((flags & EXTRA_FIELD) != 0)
-	i = 12 + src[10] + (src[11] << 8);
-    if ((flags & ORIG_NAME) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & COMMENT) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & HEAD_CRC) != 0)
-	i += 2;
-    if (i >= *lenp) {
-	printf("gunzip: ran out of data in header\n");
-	exit();
-    }
-    s.zalloc = zalloc;
-    s.zfree = zfree;
-    r = inflateInit2(&s, -MAX_WBITS);
-    if (r != Z_OK) {
-	printf("inflateInit2 returned %d\n", r);
-	exit();
-    }
-    s.next_in = src + i;
-    s.avail_in = *lenp - i;
-    s.next_out = dst;
-    s.avail_out = dstlen;
-    r = inflate(&s, Z_FINISH);
-    if (r != Z_OK && r != Z_STREAM_END) {
-	printf("inflate returned %d\n", r);
-	exit();
-    }
-    *lenp = s.next_out - (unsigned char *) dst;
-    inflateEnd(&s);
-}
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.4.0/linux/arch/ppc/config.in	Thu Nov 16 12:51:28 2000
+++ linux/arch/ppc/config.in	Mon Jan 22 15:41:14 2001
@@ -24,21 +24,24 @@
 comment 'Platform support'
 define_bool CONFIG_PPC y
 choice 'Processor Type'	\
-	"6xx/7xx/7400		CONFIG_6xx	\
+	"6xx/7xx/74xx/8260	CONFIG_6xx	\
 	 4xx			CONFIG_4xx	\
 	 POWER3               	CONFIG_POWER3	\
 	 POWER4        	        CONFIG_POWER4	\
-	 8260			CONFIG_8260	\
 	 8xx			CONFIG_8xx"	6xx
 
+if [ "$CONFIG_6xx" = "y" ]; then
+  bool 'MPC8260 CPM Support' CONFIG_8260
+fi
+
 if [ "$CONFIG_POWER3" = "y" -o "$CONFIG_POWER4" = "y" ]; then
   define_bool CONFIG_PPC64BRIDGE y
   define_bool CONFIG_ALL_PPC y
 fi
- 
+
 if [ "$CONFIG_8260" = "y" ]; then
-  define_bool CONFIG_6xx y
   define_bool CONFIG_SERIAL_CONSOLE y
+  bool 'Support for EST8260' CONFIG_EST8260
 fi
 
 if [ "$CONFIG_4xx" = "y" ]; then
@@ -59,25 +62,32 @@
 	 TQM860		CONFIG_TQM860		\
 	 MBX		CONFIG_MBX		\
 	 WinCept	CONFIG_WINCEPT"		RPX-Lite
+	 
+  if [ "$CONFIG_TQM8xxL" = "y" ]; then
+    bool 'FPS850 Mainboard' CONFIG_FPS850
+  fi
 fi
-if [ "$CONFIG_6xx" = "y" ]; then
+
+if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ]; then
   choice 'Machine Type'		\
 	"PowerMac/PReP/MTX/CHRP	CONFIG_ALL_PPC	\
-	 Gemini		CONFIG_GEMINI		\
-	 EST8260	CONFIG_EST8260		\
 	 APUS		CONFIG_APUS"		PowerMac/PReP/MTX/CHRP
 fi
 
+if [ "$CONFIG_PPC64BRIDGE" != "y" ]; then
+  bool 'Workarounds for PPC601 bugs' CONFIG_PPC601_SYNC_FIX
+fi
+
 if [ "$CONFIG_8xx" = "y" -o "$CONFIG_8260" = "y" ]; then
   define_bool CONFIG_ALL_PPC n
 fi
 
-if [ "$CONFIG_TQM8xxL" = "y" ]; then
-  bool 'FPS850 Mainboard' CONFIG_FPS850
+bool 'Symmetric multi-processing support' CONFIG_SMP
+if [ "$CONFIG_SMP" = "y" ]; then
+  bool '  Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
 fi
 
-bool 'Symmetric multi-processing support' CONFIG_SMP
-if [ "$CONFIG_6xx" = "y" ];then
+if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then
   bool 'AltiVec Support' CONFIG_ALTIVEC
 fi
 
@@ -106,14 +116,14 @@
 
 if [ "$CONFIG_APUS" = "y" -o "$CONFIG_4xx" = "y" -o \
      "$CONFIG_8260" = "y" ]; then
-   define_bool CONFIG_PCI n
+  define_bool CONFIG_PCI n
 else
-   if [ "$CONFIG_8xx" = "y" ]; then
-      bool 'QSpan PCI' CONFIG_PCI_QSPAN
-      define_bool CONFIG_PCI $CONFIG_PCI_QSPAN
-   else
-      define_bool CONFIG_PCI y
-   fi
+  if [ "$CONFIG_8xx" = "y" ]; then
+     bool 'QSpan PCI' CONFIG_PCI_QSPAN
+     define_bool CONFIG_PCI $CONFIG_PCI_QSPAN
+  else
+     define_bool CONFIG_PCI y
+  fi
 fi
 
 bool 'Networking support' CONFIG_NET
@@ -123,40 +133,34 @@
 
 # only elf supported, a.out is not -- Cort
 if [ "$CONFIG_PROC_FS" = "y" ]; then
-   define_bool CONFIG_KCORE_ELF y
+  define_bool CONFIG_KCORE_ELF y
 fi
 define_bool CONFIG_BINFMT_ELF y
 define_bool CONFIG_KERNEL_ELF y
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 source drivers/pci/Config.in
-source drivers/zorro/Config.in
 
 bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
 
 if [ "$CONFIG_HOTPLUG" = "y" ]; then
-   source drivers/pcmcia/Config.in
+  source drivers/pcmcia/Config.in
 else
-   define_bool CONFIG_PCMCIA n
+  define_bool CONFIG_PCMCIA n
 fi
 
 source drivers/parport/Config.in
 
 if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
-  bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
-  bool 'Support for frame buffer devices' CONFIG_FB
-  if [ "$CONFIG_FB" = "y" ]; then
-    bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
-  fi
-
   tristate 'Support for /dev/rtc' CONFIG_PPC_RTC
-  bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
-  bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
-  bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP
 fi
 
-if [ "$CONFIG_PREP" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
-  bool 'PReP bootloader kernel arguments' CONFIG_CMDLINE_BOOL
+if [ "$CONFIG_ALL_PPC" = "y" ]; then
+  bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
+  bool 'Support for RTAS (RunTime Abstraction Services) in /proc' CONFIG_PPC_RTAS
+  bool 'Support for early boot text console (BootX or OpenFirmware only)' CONFIG_BOOTX_TEXT
+  bool 'Support for PReP Residual Data' CONFIG_PREP_RESIDUAL
+  bool 'Default bootloader kernel arguments' CONFIG_CMDLINE_BOOL
   if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then
     string 'Initial kernel command string' CONFIG_CMDLINE "console=ttyS0,9600 console=tty0 root=/dev/sda2"
   fi
@@ -181,6 +185,7 @@
   fi
   bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT
   bool '/proc/hardware support' CONFIG_PROC_HARDWARE
+  source drivers/zorro/Config.in
 fi
 
 endmenu
@@ -254,7 +259,13 @@
 
 mainmenu_option next_comment
 comment 'Console drivers'
-source drivers/video/Config.in
+if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
+  bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
+fi
+ source drivers/video/Config.in
+if [ "$CONFIG_FB" = "y" -a "$CONFIG_ALL_PPC" = "y" ]; then
+  bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
+fi
 endmenu
 
 source drivers/input/Config.in
@@ -267,29 +278,26 @@
   bool 'Support for CUDA based PowerMacs' CONFIG_ADB_CUDA
   bool 'Support for PMU  based PowerMacs' CONFIG_ADB_PMU
   if [ "$CONFIG_ADB_PMU" = "y" ]; then
-     bool '   Power management support for PowerBooks' CONFIG_PMAC_PBOOK
-     # made a separate option since backlight may end up beeing used
-     # on non-powerbook machines (but only on PMU based ones AFAIK)
-     bool '   Backlight control for LCD screens' CONFIG_PMAC_BACKLIGHT
+    bool '   Power management support for PowerBooks' CONFIG_PMAC_PBOOK
+    # made a separate option since backlight may end up beeing used
+    # on non-powerbook machines (but only on PMU based ones AFAIK)
+    bool '   Backlight control for LCD screens' CONFIG_PMAC_BACKLIGHT
   fi
   bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
   tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
   if [ "$CONFIG_MAC_SERIAL" = "y" ]; then
-     bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
+    bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
   fi
   bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB
   if [ "$CONFIG_ADB" = "y" ]; then
-     bool '   Include MacIO (CHRP) ADB driver' CONFIG_ADB_MACIO
-  fi
-fi
-if [ "$CONFIG_ADB" = "y" ]; then
-  dep_bool '   Use input layer for ADB devices' CONFIG_INPUT_ADBHID $CONFIG_INPUT
-  if [ "$CONFIG_INPUT_ADBHID" = "y" ]; then
-     define_bool CONFIG_MAC_HID y
-     bool '     Support for ADB raw keycodes' CONFIG_MAC_ADBKEYCODES
-     bool '     Support for mouse button 2+3 emulation' CONFIG_MAC_EMUMOUSEBTN
-  else
-     bool '   Support for ADB keyboard (old driver)' CONFIG_ADB_KEYBOARD
+    bool '   Include MacIO (CHRP) ADB driver' CONFIG_ADB_MACIO
+    dep_bool '   Use input layer for ADB devices' CONFIG_INPUT_ADBHID $CONFIG_INPUT
+    if [ "$CONFIG_INPUT_ADBHID" = "y" ]; then
+      bool '     Support for ADB raw keycodes' CONFIG_MAC_ADBKEYCODES
+      bool '     Support for mouse button 2+3 emulation' CONFIG_MAC_EMUMOUSEBTN
+    else
+      bool '   Support for ADB keyboard (old driver)' CONFIG_ADB_KEYBOARD
+    fi
   fi
 fi
 endmenu
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/apus_defconfig linux/arch/ppc/configs/apus_defconfig
--- v2.4.0/linux/arch/ppc/configs/apus_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/apus_defconfig	Mon Jan 22 15:41:14 2001
@@ -11,9 +11,7 @@
 #
 # Loadable module support
 #
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES is not set
 
 #
 # Platform support
@@ -23,14 +21,14 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 # CONFIG_8xx is not set
-CONFIG_ALL_PPC=y
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_APUS is not set
+# CONFIG_8260 is not set
+# CONFIG_ALL_PPC is not set
+CONFIG_APUS=y
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
 # CONFIG_ALTIVEC is not set
+CONFIG_MACH_SPECIFIC=y
 
 #
 # General setup
@@ -38,8 +36,10 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_MOL is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
-CONFIG_PCI=y
+# CONFIG_MCA is not set
+# CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
@@ -47,23 +47,35 @@
 CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=m
-# CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
 # CONFIG_PCMCIA is not set
 
 #
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_PPC_RTC=y
+CONFIG_FB_CONSOLE=y
+CONFIG_AMIGA=y
+CONFIG_ZORRO=y
+CONFIG_AMIGAMOUSE=y
+CONFIG_ABSTRACT_CONSOLE=y
 CONFIG_FB=y
-CONFIG_FB_COMPAT_XPMAC=y
-# CONFIG_PPC_RTC is not set
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_BOOTX_TEXT is not set
-# CONFIG_MOTOROLA_HOTSWAP is not set
-# CONFIG_CMDLINE_BOOL is not set
+CONFIG_AMIGA_BUILTIN_SERIAL=y
+# CONFIG_M68K_PRINTER is not set
+CONFIG_GVPIOEXT=y
+# CONFIG_GVPIOEXT_LP is not set
+CONFIG_GVPIOEXT_PLIP=y
+CONFIG_MULTIFACE_III_TTY=y
+# CONFIG_SERIAL_CONSOLE is not set
+CONFIG_HEARTBEAT=y
+CONFIG_PROC_HARDWARE=y
+CONFIG_ZORRO_NAMES=y
 
 #
 # Memory Technology Devices (MTD)
@@ -80,12 +92,14 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
+CONFIG_AMIGA_FLOPPY=y
+CONFIG_AMIGA_Z2RAM=y
 # 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_LOOP=y
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
@@ -106,21 +120,17 @@
 #
 # Networking options
 #
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK=y
-# CONFIG_RTNETLINK is not set
-# CONFIG_NETLINK_DEV is not set
+# CONFIG_PACKET 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=y
+# CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_PNP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -131,7 +141,7 @@
 #  
 #
 # CONFIG_IPX is not set
-CONFIG_ATALK=m
+# CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
@@ -151,9 +161,48 @@
 #
 # ATA/IDE/MFM/RLL support
 #
-# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
+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=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+CONFIG_BLK_DEV_GAYLE=y
+CONFIG_BLK_DEV_IDEDOUBLER=y
+CONFIG_BLK_DEV_BUDDHA=y
+# 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
@@ -165,7 +214,8 @@
 #
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
@@ -176,29 +226,23 @@
 #
 # CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 
 #
 # SCSI low-level drivers
 #
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
-CONFIG_SCSI_AIC7XXX=y
-# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
-CONFIG_AIC7XXX_PROC_STATS=y
-CONFIG_AIC7XXX_RESET_DELAY=15
+# CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
@@ -211,30 +255,18 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=5
-CONFIG_SCSI_MAC53C94=y
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
 
 #
 # Network device support
@@ -245,34 +277,30 @@
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_APPLETALK is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-CONFIG_MACE=y
-CONFIG_BMAC=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
-# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
+CONFIG_ARIADNE=y
+# CONFIG_NE2K_ZORRO is not set
+CONFIG_A2065=y
+CONFIG_HYDRA=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 is not set
 # CONFIG_NET_POCKET is not set
@@ -287,13 +315,16 @@
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
 # CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
 
 #
 # Wireless LAN (non-hamradio)
@@ -336,44 +367,47 @@
 #
 # Console drivers
 #
+# CONFIG_VGA_CONSOLE is not set
 
 #
 # 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_CLGEN=y
+CONFIG_FB_PM2=y
+CONFIG_FB_PM2_CVPPC=y
 # CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-CONFIG_FB_CONTROL=y
-CONFIG_FB_PLATINUM=y
-CONFIG_FB_VALKYRIE=y
-CONFIG_FB_CT65550=y
-CONFIG_FB_IMSTT=y
+CONFIG_FB_AMIGA=y
+CONFIG_FB_AMIGA_OCS=y
+CONFIG_FB_AMIGA_ECS=y
+CONFIG_FB_AMIGA_AGA=y
+CONFIG_FB_CYBER=y
+CONFIG_FB_VIRGE=y
+CONFIG_FB_RETINAZ3=y
+# CONFIG_FB_FM2 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_SIS is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_MFB=y
 CONFIG_FBCON_CFB8=y
 CONFIG_FBCON_CFB16=y
 CONFIG_FBCON_CFB24=y
 CONFIG_FBCON_CFB32=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
+CONFIG_FBCON_AFB=y
+CONFIG_FBCON_ILBM=y
+CONFIG_FBCON_FONTWIDTH8_ONLY=y
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
-CONFIG_FONT_SUN8x16=y
-CONFIG_FONT_SUN12x22=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_PEARL_8x8=y
 
 #
 # Input core support
@@ -383,23 +417,17 @@
 #
 # Macintosh device drivers
 #
-# CONFIG_ADB_CUDA is not set
-# CONFIG_ADB_PMU is not set
-CONFIG_MAC_FLOPPY=y
-CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_ADB is not set
 
 #
 # Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=m
+CONFIG_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+# CONFIG_UNIX98_PTYS is not set
 
 #
 # I2C support
@@ -427,7 +455,7 @@
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_INTEL_RNG is not set
-CONFIG_NVRAM=y
+# CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -449,24 +477,24 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
+CONFIG_AFFS_FS=y
 CONFIG_HFS_FS=y
 # CONFIG_BFS_FS is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
 # CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=m
+CONFIG_VFAT_FS=y
 # 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=y
 # CONFIG_JOLIET is not set
-# CONFIG_MINIX_FS is not set
+CONFIG_MINIX_FS=y
 # CONFIG_NTFS_FS is not set
 # CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
@@ -474,7 +502,7 @@
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVFS_MOUNT is not set
 # CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
+# CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
@@ -493,7 +521,7 @@
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
 # CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=y
+# CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
@@ -505,8 +533,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
 
@@ -514,14 +540,15 @@
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_SMB_NLS is not set
 CONFIG_NLS=y
 
 #
 # Native Language Support
 #
 CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_437 is not set
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -541,7 +568,7 @@
 # CONFIG_NLS_CODEPAGE_936 is not set
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -558,23 +585,7 @@
 #
 # Sound
 #
-CONFIG_SOUND=y
-# CONFIG_DMASOUND_AWACS is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND is not set
 
 #
 # USB support
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/bseip_defconfig linux/arch/ppc/configs/bseip_defconfig
--- v2.4.0/linux/arch/ppc/configs/bseip_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/bseip_defconfig	Mon Jan 22 15:41:14 2001
@@ -21,7 +21,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -32,6 +31,7 @@
 # CONFIG_TQM860 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -43,7 +43,9 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_MOL is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 # CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -182,7 +184,6 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
-# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -190,7 +191,6 @@
 # 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
@@ -377,8 +377,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
 
@@ -395,6 +393,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig
--- v2.4.0/linux/arch/ppc/configs/common_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/common_defconfig	Mon Jan 22 15:41:14 2001
@@ -23,12 +23,11 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 # CONFIG_8xx is not set
+# CONFIG_8260 is not set
 CONFIG_ALL_PPC=y
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
 # CONFIG_APUS is not set
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
 CONFIG_ALTIVEC=y
 
@@ -36,9 +35,11 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
+CONFIG_MOL=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -49,21 +50,24 @@
 CONFIG_KERNEL_ELF=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
 # CONFIG_PCMCIA is not set
 
 #
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
-CONFIG_VGA_CONSOLE=y
-CONFIG_FB=y
-CONFIG_FB_COMPAT_XPMAC=y
 CONFIG_PPC_RTC=y
 CONFIG_PROC_DEVICETREE=y
+CONFIG_PPC_RTAS=y
 CONFIG_BOOTX_TEXT=y
-# CONFIG_MOTOROLA_HOTSWAP is not set
-# CONFIG_CMDLINE_BOOL is not set
+CONFIG_PREP_RESIDUAL=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600 console=tty0 root=/dev/sda2"
 
 #
 # Memory Technology Devices (MTD)
@@ -79,7 +83,7 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=m
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
@@ -111,7 +115,8 @@
 CONFIG_NETLINK=y
 # CONFIG_RTNETLINK is not set
 # CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -123,6 +128,34 @@
 # CONFIG_IP_MROUTE is not set
 # CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
+
+#
+#   IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+CONFIG_IP_NF_NAT_NEEDED=y
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
@@ -239,6 +272,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=y
 CONFIG_SR_EXTRA_DEVS=2
@@ -344,7 +378,6 @@
 CONFIG_MACE=y
 CONFIG_BMAC=y
 CONFIG_GMAC=y
-# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -357,27 +390,28 @@
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
 # CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
-CONFIG_DE4X5=y
-# CONFIG_TULIP is not set
+CONFIG_TULIP=y
+CONFIG_DE4X5=m
 # CONFIG_DGRS is not set
 # CONFIG_DM9102 is not set
 # CONFIG_EEPRO100 is not set
+# CONFIG_EEPRO100_PM is not set
 # CONFIG_LNE390 is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
-# CONFIG_RTL8129 is not set
 # CONFIG_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_NET_POCKET is not set
 
 #
@@ -439,6 +473,7 @@
 #
 # Console drivers
 #
+CONFIG_VGA_CONSOLE=y
 
 #
 # Frame-buffer support
@@ -460,7 +495,8 @@
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_G100 is not set
+# CONFIG_FB_MATROX_G450 is not set
 # CONFIG_FB_MATROX_MULTIHEAD is not set
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY128=y
@@ -481,6 +517,7 @@
 # CONFIG_FONT_6x11 is not set
 # CONFIG_FONT_PEARL_8x8 is not set
 # CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FB_COMPAT_XPMAC is not set
 
 #
 # Input core support
@@ -498,15 +535,13 @@
 #
 CONFIG_ADB_CUDA=y
 CONFIG_ADB_PMU=y
-CONFIG_PMAC_PBOOK=y
-CONFIG_PMAC_BACKLIGHT=y
-CONFIG_MAC_FLOPPY=y
-CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
+# CONFIG_PMAC_PBOOK is not set
+# CONFIG_PMAC_BACKLIGHT is not set
+# CONFIG_MAC_FLOPPY is not set
+CONFIG_MAC_SERIAL=m
 CONFIG_ADB=y
 CONFIG_ADB_MACIO=y
 CONFIG_INPUT_ADBHID=y
-CONFIG_MAC_HID=y
 CONFIG_MAC_ADBKEYCODES=y
 CONFIG_MAC_EMUMOUSEBTN=y
 
@@ -575,17 +610,17 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS 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_HFS_FS=m
 # CONFIG_BFS_FS is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
+CONFIG_VFAT_FS=m
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
@@ -631,8 +666,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
 
@@ -652,6 +685,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 CONFIG_NLS=y
 
 #
@@ -678,7 +712,7 @@
 # CONFIG_NLS_CODEPAGE_936 is not set
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -695,9 +729,9 @@
 #
 # Sound
 #
-CONFIG_SOUND=y
-CONFIG_DMASOUND_AWACS=y
-CONFIG_DMASOUND=y
+CONFIG_SOUND=m
+CONFIG_DMASOUND_AWACS=m
+CONFIG_DMASOUND=m
 # CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_FUSION is not set
@@ -711,43 +745,14 @@
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
-CONFIG_SOUND_OSS=y
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_ACI_MIXER is not set
-CONFIG_SOUND_CS4232=m
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_PAS_JOYSTICK is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_YMPCI is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
+# CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
 
 #
 # USB support
 #
 CONFIG_USB=y
-CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEBUG is not set
 
 #
 # Miscellaneous USB options
@@ -763,33 +768,69 @@
 CONFIG_USB_OHCI=y
 
 #
-# USB Devices
+# USB Device Class drivers
 #
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+CONFIG_USB_ACM=m
 # CONFIG_USB_PRINTER is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_WACOM is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
 # CONFIG_USB_SCANNER is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
+
+#
+# USB Multimedia devices
+#
 # CONFIG_USB_IBMCAM is not set
 # CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_USS720 is not set
+# CONFIG_USB_DSBR is not set
 # CONFIG_USB_DABUSB is not set
+
+#
+# USB Network adaptors
+#
 # CONFIG_USB_PLUSB is not set
 # CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_BLUETOOTH is not set
 # CONFIG_USB_NET1080 is not set
 
 #
-# USB Human Interface Devices (HID)
+# USB port drivers
 #
-CONFIG_USB_HID=y
-# CONFIG_USB_WACOM is not set
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB misc drivers
+#
+# CONFIG_USB_RIO500 is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/est8260_defconfig linux/arch/ppc/configs/est8260_defconfig
--- v2.4.0/linux/arch/ppc/configs/est8260_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/est8260_defconfig	Mon Jan 22 15:41:14 2001
@@ -17,21 +17,17 @@
 # Platform support
 #
 CONFIG_PPC=y
-# CONFIG_6xx is not set
+CONFIG_6xx=y
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-CONFIG_8260=y
 # CONFIG_8xx is not set
-CONFIG_6xx=y
+CONFIG_8260=y
 CONFIG_SERIAL_CONSOLE=y
-# CONFIG_ALL_PPC is not set
-# CONFIG_GEMINI is not set
 CONFIG_EST8260=y
-# CONFIG_APUS is not set
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-# CONFIG_ALTIVEC is not set
 CONFIG_MACH_SPECIFIC=y
 
 #
@@ -40,7 +36,9 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_MOL is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -57,12 +55,7 @@
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_FB is not set
 # CONFIG_PPC_RTC is not set
-# CONFIG_PROC_DEVICETREE is not set
-# CONFIG_BOOTX_TEXT is not set
-# CONFIG_MOTOROLA_HOTSWAP is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -184,7 +177,6 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
-# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -192,7 +184,6 @@
 # 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
@@ -250,6 +241,7 @@
 #
 # Console drivers
 #
+# CONFIG_VGA_CONSOLE is not set
 
 #
 # Frame-buffer support
@@ -379,8 +371,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
 
@@ -397,6 +387,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/gemini_defconfig linux/arch/ppc/configs/gemini_defconfig
--- v2.4.0/linux/arch/ppc/configs/gemini_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/gemini_defconfig	Wed Dec 31 16:00:00 1969
@@ -1,484 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-# CONFIG_UID16 is not set
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_6xx=y
-# CONFIG_4xx is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
-# CONFIG_8xx is not set
-# CONFIG_ALL_PPC is not set
-CONFIG_GEMINI=y
-# CONFIG_EST8260 is not set
-# CONFIG_APUS is not set
-# CONFIG_SMP is not set
-CONFIG_ALTIVEC=y
-CONFIG_MACH_SPECIFIC=y
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
-# CONFIG_ISA is not set
-# CONFIG_SBUS is not set
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_SYSCTL=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_FB is not set
-# CONFIG_PPC_RTC is not set
-# CONFIG_PROC_DEVICETREE is not set
-# CONFIG_BOOTX_TEXT is not set
-# CONFIG_MOTOROLA_HOTSWAP is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP 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
-# CONFIG_LVM_PROC_FS is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK=y
-# CONFIG_RTNETLINK is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-# 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
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-# CONFIG_CHR_DEV_ST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
-# CONFIG_SCSI_SYM53C8XX is not set
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=20
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SIM710 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 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_ETHERTAP is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_GMAC is not set
-CONFIG_NCR885E=y
-# CONFIG_OAKNET is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI 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
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA 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
-
-#
-# Console drivers
-#
-
-#
-# Frame-buffer support
-#
-# CONFIG_FB is not set
-
-#
-# Input core support
-#
-# CONFIG_INPUT is not set
-
-#
-# Macintosh device drivers
-#
-
-#
-# Character devices
-#
-# CONFIG_VT 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=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# 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
-#
-# 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_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=y
-# 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=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_SYSV_FS_WRITE is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# 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 is not set
-# 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_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS 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_NLS is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/ibmchrp_defconfig linux/arch/ppc/configs/ibmchrp_defconfig
--- v2.4.0/linux/arch/ppc/configs/ibmchrp_defconfig	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/configs/ibmchrp_defconfig	Mon Jan 22 15:41:14 2001
@@ -0,0 +1,636 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+# CONFIG_UID16 is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_6xx=y
+# CONFIG_4xx is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8260 is not set
+# CONFIG_8xx is not set
+CONFIG_ALL_PPC=y
+# CONFIG_GEMINI is not set
+# CONFIG_APUS is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_SMP is not set
+# CONFIG_ALTIVEC is not set
+
+#
+# General setup
+#
+CONFIG_HIGHMEM=y
+# CONFIG_MOL is not set
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_PCI=y
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+CONFIG_PPC_RTC=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_PPC_RTAS=y
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PREP_RESIDUAL is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+# 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=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD 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
+# CONFIG_LVM_PROC_FS is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK=y
+# CONFIG_RTNETLINK is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+
+#
+#   IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+CONFIG_IP_NF_NAT_NEEDED=y
+# CONFIG_IP_NF_COMPAT_IPFWADM 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
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+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=y
+CONFIG_SR_EXTRA_DEVS=2
+CONFIG_CHR_DEV_SG=y
+# CONFIG_SCSI_DEBUG_QUEUES is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 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_ETHERTAP is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
+# CONFIG_OAKNET is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TULIP is not set
+CONFIG_DE4X5=y
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_EEPRO100_PM is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_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_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=y
+# CONFIG_IBMTR is not set
+CONFIG_IBMOL=y
+# CONFIG_IBMLS is not set
+# CONFIG_TMS380TR is not set
+# CONFIG_SMCTR 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
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA 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
+
+#
+# Console drivers
+#
+CONFIG_VGA_CONSOLE=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_OF=y
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA16 is not set
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_G450 is not set
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+CONFIG_FB_3DFX=y
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FB_COMPAT_XPMAC is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+
+#
+# Macintosh device drivers
+#
+# CONFIG_ADB_CUDA is not set
+# CONFIG_ADB_PMU is not set
+# CONFIG_MAC_FLOPPY is not set
+# CONFIG_MAC_SERIAL is not set
+# CONFIG_ADB is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# 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=y
+CONFIG_RTC=y
+# 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_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=m
+CONFIG_MSDOS_FS=m
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=m
+# 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=y
+# 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=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_NFS_FS is not set
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
+# 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=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_KGDB is not set
+CONFIG_XMON=y
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/mbx_defconfig linux/arch/ppc/configs/mbx_defconfig
--- v2.4.0/linux/arch/ppc/configs/mbx_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/mbx_defconfig	Mon Jan 22 15:41:14 2001
@@ -21,7 +21,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -32,6 +31,7 @@
 # CONFIG_TQM860 is not set
 CONFIG_MBX=y
 # CONFIG_WINCEPT is not set
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -43,7 +43,9 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_MOL is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 # CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -176,7 +178,6 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
-# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -184,7 +185,6 @@
 # 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
@@ -370,8 +370,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
 
@@ -388,6 +386,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/oak_defconfig linux/arch/ppc/configs/oak_defconfig
--- v2.4.0/linux/arch/ppc/configs/oak_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/oak_defconfig	Mon Jan 22 15:41:15 2001
@@ -12,7 +12,7 @@
 # Loadable module support
 #
 CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
 CONFIG_KMOD=y
 
 #
@@ -23,10 +23,10 @@
 CONFIG_4xx=y
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 # CONFIG_8xx is not set
 CONFIG_OAK=y
 # CONFIG_WALNUT is not set
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
 # CONFIG_MATH_EMULATION is not set
@@ -37,7 +37,9 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_MOL is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -171,7 +173,6 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
-# CONFIG_NCR885E is not set
 CONFIG_OAKNET=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -179,7 +180,6 @@
 # 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
@@ -366,8 +366,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
 
@@ -376,6 +374,7 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/power3_defconfig linux/arch/ppc/configs/power3_defconfig
--- v2.4.0/linux/arch/ppc/configs/power3_defconfig	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/configs/power3_defconfig	Mon Jan 22 15:41:15 2001
@@ -0,0 +1,662 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+# CONFIG_UID16 is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+# CONFIG_6xx is not set
+# CONFIG_4xx is not set
+CONFIG_POWER3=y
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_PPC64BRIDGE=y
+CONFIG_ALL_PPC=y
+CONFIG_SMP=y
+
+#
+# General setup
+#
+CONFIG_HIGHMEM=y
+# CONFIG_MOL is not set
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_PCI=y
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_SUNBPP is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+# CONFIG_PPC_RTC is not set
+CONFIG_PROC_DEVICETREE=y
+CONFIG_PPC_RTAS=y
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PREP_RESIDUAL is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+# 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=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_BOOT is not set
+# CONFIG_AUTODETECT_RAID is not set
+CONFIG_BLK_DEV_LVM=y
+CONFIG_LVM_PROC_FS=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK=y
+# CONFIG_RTNETLINK is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# 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
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+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=y
+CONFIG_SR_EXTRA_DEVS=2
+CONFIG_CHR_DEV_SG=y
+# CONFIG_SCSI_DEBUG_QUEUES is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 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_ETHERTAP is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_OAKNET is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TULIP is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_EEPRO100_PM is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_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_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_PLIP 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=y
+# CONFIG_IBMTR is not set
+CONFIG_IBMOL=y
+# CONFIG_IBMLS is not set
+# CONFIG_TMS380TR is not set
+# CONFIG_SMCTR 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
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA 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
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# 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_OF=y
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA16 is not set
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_I2C=y
+# CONFIG_FB_MATROX_MAVEN is not set
+# CONFIG_FB_MATROX_G450 is not set
+CONFIG_FB_MATROX_MULTIHEAD=y
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FB_COMPAT_XPMAC is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+
+#
+# Macintosh device drivers
+#
+# CONFIG_ADB_CUDA is not set
+# CONFIG_ADB_PMU is not set
+# CONFIG_MAC_FLOPPY is not set
+# CONFIG_MAC_SERIAL is not set
+# CONFIG_ADB is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=2048
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_PHILIPSPAR is not set
+# CONFIG_I2C_ELV is not set
+# CONFIG_I2C_VELLEMAN is not set
+CONFIG_I2C_ALGOPCF=y
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_CHARDEV=y
+
+#
+# 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
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+CONFIG_NVRAM=y
+# 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=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=y
+# 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=y
+CONFIG_JOLIET=y
+# 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=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# 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 is not set
+CONFIG_NFSD=y
+# 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=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+# CONFIG_DMASOUND_AWACS is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+CONFIG_SOUND_OSS=y
+CONFIG_SOUND_TRACEINIT=y
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+CONFIG_SOUND_CS4232=m
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+CONFIG_SOUND_MSS=m
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMPCI is not set
+# CONFIG_SOUND_YMFPCI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_TVMIXER=y
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_KGDB is not set
+CONFIG_XMON=y
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/rpxcllf_defconfig linux/arch/ppc/configs/rpxcllf_defconfig
--- v2.4.0/linux/arch/ppc/configs/rpxcllf_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/rpxcllf_defconfig	Mon Jan 22 15:41:15 2001
@@ -21,7 +21,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -32,6 +31,7 @@
 # CONFIG_TQM860 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -43,7 +43,9 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_MOL is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 # CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -182,7 +184,6 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
-# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -190,7 +191,6 @@
 # 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
@@ -377,8 +377,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
 
@@ -395,6 +393,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/rpxlite_defconfig linux/arch/ppc/configs/rpxlite_defconfig
--- v2.4.0/linux/arch/ppc/configs/rpxlite_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/rpxlite_defconfig	Mon Jan 22 15:41:15 2001
@@ -21,7 +21,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 CONFIG_RPXLITE=y
@@ -32,6 +31,7 @@
 # CONFIG_TQM860 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -43,7 +43,9 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_MOL is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 # CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -182,7 +184,6 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
-# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -190,7 +191,6 @@
 # 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
@@ -377,8 +377,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
 
@@ -395,6 +393,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/configs/walnut_defconfig linux/arch/ppc/configs/walnut_defconfig
--- v2.4.0/linux/arch/ppc/configs/walnut_defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/configs/walnut_defconfig	Mon Jan 22 15:41:15 2001
@@ -12,7 +12,7 @@
 # Loadable module support
 #
 CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
 CONFIG_KMOD=y
 
 #
@@ -23,10 +23,10 @@
 CONFIG_4xx=y
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 # CONFIG_8xx is not set
 # CONFIG_OAK is not set
 CONFIG_WALNUT=y
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
 # CONFIG_MATH_EMULATION is not set
@@ -37,7 +37,9 @@
 # CONFIG_HIGHMEM is not set
 # CONFIG_MOL is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -171,7 +173,6 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
-# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -179,7 +180,6 @@
 # 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
@@ -369,8 +369,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
 
@@ -379,6 +377,7 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.4.0/linux/arch/ppc/defconfig	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/defconfig	Mon Jan 22 15:41:15 2001
@@ -23,12 +23,11 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 # CONFIG_8xx is not set
+# CONFIG_8260 is not set
 CONFIG_ALL_PPC=y
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
 # CONFIG_APUS is not set
+CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
 CONFIG_ALTIVEC=y
 
@@ -36,9 +35,11 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
+CONFIG_MOL=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -49,21 +50,24 @@
 CONFIG_KERNEL_ELF=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
 # CONFIG_PCMCIA is not set
 
 #
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
-CONFIG_VGA_CONSOLE=y
-CONFIG_FB=y
-CONFIG_FB_COMPAT_XPMAC=y
 CONFIG_PPC_RTC=y
 CONFIG_PROC_DEVICETREE=y
+CONFIG_PPC_RTAS=y
 CONFIG_BOOTX_TEXT=y
-# CONFIG_MOTOROLA_HOTSWAP is not set
-# CONFIG_CMDLINE_BOOL is not set
+CONFIG_PREP_RESIDUAL=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600 console=tty0 root=/dev/sda2"
 
 #
 # Memory Technology Devices (MTD)
@@ -79,7 +83,7 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=m
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
@@ -111,7 +115,8 @@
 CONFIG_NETLINK=y
 # CONFIG_RTNETLINK is not set
 # CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -123,6 +128,34 @@
 # CONFIG_IP_MROUTE is not set
 # CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
+
+#
+#   IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+CONFIG_IP_NF_NAT_NEEDED=y
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
@@ -239,6 +272,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=y
 CONFIG_SR_EXTRA_DEVS=2
@@ -344,7 +378,6 @@
 CONFIG_MACE=y
 CONFIG_BMAC=y
 CONFIG_GMAC=y
-# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -357,27 +390,28 @@
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
 # CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
-CONFIG_DE4X5=y
-# CONFIG_TULIP is not set
+CONFIG_TULIP=y
+CONFIG_DE4X5=m
 # CONFIG_DGRS is not set
 # CONFIG_DM9102 is not set
 # CONFIG_EEPRO100 is not set
+# CONFIG_EEPRO100_PM is not set
 # CONFIG_LNE390 is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
-# CONFIG_RTL8129 is not set
 # CONFIG_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_NET_POCKET is not set
 
 #
@@ -439,6 +473,7 @@
 #
 # Console drivers
 #
+CONFIG_VGA_CONSOLE=y
 
 #
 # Frame-buffer support
@@ -460,7 +495,8 @@
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_G100 is not set
+# CONFIG_FB_MATROX_G450 is not set
 # CONFIG_FB_MATROX_MULTIHEAD is not set
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY128=y
@@ -481,6 +517,7 @@
 # CONFIG_FONT_6x11 is not set
 # CONFIG_FONT_PEARL_8x8 is not set
 # CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FB_COMPAT_XPMAC is not set
 
 #
 # Input core support
@@ -498,15 +535,13 @@
 #
 CONFIG_ADB_CUDA=y
 CONFIG_ADB_PMU=y
-CONFIG_PMAC_PBOOK=y
-CONFIG_PMAC_BACKLIGHT=y
-CONFIG_MAC_FLOPPY=y
-CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
+# CONFIG_PMAC_PBOOK is not set
+# CONFIG_PMAC_BACKLIGHT is not set
+# CONFIG_MAC_FLOPPY is not set
+CONFIG_MAC_SERIAL=m
 CONFIG_ADB=y
 CONFIG_ADB_MACIO=y
 CONFIG_INPUT_ADBHID=y
-CONFIG_MAC_HID=y
 CONFIG_MAC_ADBKEYCODES=y
 CONFIG_MAC_EMUMOUSEBTN=y
 
@@ -575,17 +610,17 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS 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_HFS_FS=m
 # CONFIG_BFS_FS is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
+CONFIG_VFAT_FS=m
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
@@ -631,8 +666,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
 
@@ -652,6 +685,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 CONFIG_NLS=y
 
 #
@@ -678,7 +712,7 @@
 # CONFIG_NLS_CODEPAGE_936 is not set
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -695,9 +729,9 @@
 #
 # Sound
 #
-CONFIG_SOUND=y
-CONFIG_DMASOUND_AWACS=y
-CONFIG_DMASOUND=y
+CONFIG_SOUND=m
+CONFIG_DMASOUND_AWACS=m
+CONFIG_DMASOUND=m
 # CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_FUSION is not set
@@ -711,43 +745,14 @@
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
-CONFIG_SOUND_OSS=y
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_ACI_MIXER is not set
-CONFIG_SOUND_CS4232=m
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_PAS_JOYSTICK is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_YMPCI is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
+# CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
 
 #
 # USB support
 #
 CONFIG_USB=y
-CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEBUG is not set
 
 #
 # Miscellaneous USB options
@@ -763,33 +768,69 @@
 CONFIG_USB_OHCI=y
 
 #
-# USB Devices
+# USB Device Class drivers
 #
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+CONFIG_USB_ACM=m
 # CONFIG_USB_PRINTER is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_WACOM is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
 # CONFIG_USB_SCANNER is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
+
+#
+# USB Multimedia devices
+#
 # CONFIG_USB_IBMCAM is not set
 # CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_USS720 is not set
+# CONFIG_USB_DSBR is not set
 # CONFIG_USB_DABUSB is not set
+
+#
+# USB Network adaptors
+#
 # CONFIG_USB_PLUSB is not set
 # CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_BLUETOOTH is not set
 # CONFIG_USB_NET1080 is not set
 
 #
-# USB Human Interface Devices (HID)
+# USB port drivers
 #
-CONFIG_USB_HID=y
-# CONFIG_USB_WACOM is not set
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB misc drivers
+#
+# CONFIG_USB_RIO500 is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.4.0/linux/arch/ppc/kernel/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/ppc/kernel/Makefile	Mon Jan 22 15:41:15 2001
@@ -35,6 +35,7 @@
 					process.o signal.o bitops.o ptrace.o \
 					ppc_htab.o semaphore.o syscalls.o  \
 					align.o setup.o
+obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
 obj-$(CONFIG_POWER4)		+= xics.o
 obj-$(CONFIG_PCI)		+= pci.o pci-dma.o
 obj-$(CONFIG_KGDB)		+= ppc-stub.o
@@ -62,11 +63,8 @@
 					feature.o pmac_pci.o chrp_setup.o \
 					chrp_time.o chrp_pci.o 	open_pic.o \
 					indirect_pci.o i8259.o prep_pci.o \
-					prep_time.o prep_nvram.o ppc_ksyms.o \
-					prep_setup.o 
+					prep_time.o prep_nvram.o prep_setup.o
 obj-$(CONFIG_PMAC_BACKLIGHT)	+= pmac_backlight.o
-obj-$(CONFIG_GEMINI)		+= gemini_prom.o gemini_pci.o gemini_setup.o \
-					open_pic.o
 obj-$(CONFIG_8260)		+= m8260_setup.o ppc8260_pic.o
 
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.4.0/linux/arch/ppc/kernel/apus_setup.c	Sun Oct  8 09:33:07 2000
+++ linux/arch/ppc/kernel/apus_setup.c	Mon Jan 22 15:41:15 2001
@@ -647,25 +647,6 @@
         return 0;
 }
 
-int
-apus_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-        return 0;
-}
-
-void
-apus_ide_request_region(ide_ioreg_t from,
-			unsigned int extent,
-			const char *name)
-{
-}
-
-void
-apus_ide_release_region(ide_ioreg_t from,
-			unsigned int extent)
-{
-}
-
 void
 apus_ide_fix_driveid(struct hd_driveid *id)
 {
@@ -1131,9 +1112,6 @@
         ppc_ide_md.outsw = apus_ide_outsw;
         ppc_ide_md.default_irq = apus_ide_default_irq;
         ppc_ide_md.default_io_base = apus_ide_default_io_base;
-        ppc_ide_md.ide_check_region = apus_ide_check_region;
-        ppc_ide_md.ide_request_region = apus_ide_request_region;
-        ppc_ide_md.ide_release_region = apus_ide_release_region;
         ppc_ide_md.fix_driveid = apus_ide_fix_driveid;
         ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports;
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.4.0/linux/arch/ppc/kernel/chrp_pci.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/kernel/chrp_pci.c	Mon Jan 22 15:41:15 2001
@@ -8,8 +8,8 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/openpic.h>
 #include <linux/ide.h>
+#include <linux/bootmem.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -19,16 +19,19 @@
 #include <asm/gg2.h>
 #include <asm/machdep.h>
 #include <asm/init.h>
+#include <asm/pci-bridge.h>
 
+#include "open_pic.h"
 #include "pci.h"
 
+
 #ifdef CONFIG_POWER4
-static unsigned long pci_address_offset(int, unsigned int);
+extern unsigned long pci_address_offset(int, unsigned int);
 #endif /* CONFIG_POWER4 */
 
 /* LongTrail */
-#define pci_config_addr(bus, dev, offset) \
-(GG2_PCI_CONFIG_BASE | ((bus)<<16) | ((dev)<<8) | (offset))
+#define pci_config_addr(dev, offset) \
+(GG2_PCI_CONFIG_BASE | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset))
 
 volatile struct Hydra *Hydra = NULL;
 
@@ -37,205 +40,127 @@
  * limit the bus number to 3 bits
  */
 
-int __chrp gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-				 unsigned char offset, unsigned char *val)
-{
-	if (bus > 7) {
-		*val = 0xff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	*val = in_8((unsigned char *)pci_config_addr(bus, dev_fn, offset));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int __chrp gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-				 unsigned char offset, unsigned short *val)
-{
-	if (bus > 7) {
-		*val = 0xffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	*val = in_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset));
-	return PCIBIOS_SUCCESSFUL;
-}
-
+#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
 
-int __chrp gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned int *val)
-{
-	if (bus > 7) {
-		*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	*val = in_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int __chrp gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned char val)
-{
-	if (bus > 7)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_8((unsigned char *)pci_config_addr(bus, dev_fn, offset), val);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int __chrp gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned short val)
-{
-	if (bus > 7)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset), val);
-	return PCIBIOS_SUCCESSFUL;
-}
+#define cfg_read_bad(val, size)		*val = bad_##size;
+#define cfg_write_bad(val, size)
 
-int __chrp gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned int val)
-{
-	if (bus > 7)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset), val);
-	return PCIBIOS_SUCCESSFUL;
-}
+#define bad_byte	0xff
+#define bad_word	0xffff
+#define bad_dword	0xffffffffU
+
+#define GG2_PCI_OP(rw, size, type, op)					    \
+int __chrp gg2_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
+{									    \
+	if (dev->bus->number > 7) {					    \
+		cfg_##rw##_bad(val, size)				    \
+		return PCIBIOS_DEVICE_NOT_FOUND;			    \
+	}								    \
+	cfg_##rw(val, pci_config_addr(dev, off), type, op);		    \
+	return PCIBIOS_SUCCESSFUL;					    \
+}
+
+GG2_PCI_OP(read, byte, u8 *, in_8)
+GG2_PCI_OP(read, word, u16 *, in_le16)
+GG2_PCI_OP(read, dword, u32 *, in_le32)
+GG2_PCI_OP(write, byte, u8, out_8)
+GG2_PCI_OP(write, word, u16, out_le16)
+GG2_PCI_OP(write, dword, u32, out_le32)
+
+static struct pci_ops gg2_pci_ops =
+{
+	gg2_read_config_byte,
+	gg2_read_config_word,
+	gg2_read_config_dword,
+	gg2_write_config_byte,
+	gg2_write_config_word,
+	gg2_write_config_dword
+};
 
-#define python_config_address(bus) (unsigned *)((0xfef00000+0xf8000)-(bus*0x100000))
-#define python_config_data(bus) ((0xfef00000+0xf8010)-(bus*0x100000))
-#define PYTHON_CFA(b, d, o)	(0x80 | ((b<<6) << 8) | ((d) << 16) \
+/*
+ * Access functions for PCI config space on IBM "python" host bridges.
+ */
+#define PYTHON_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
 				 | (((o) & ~3) << 24))
-unsigned int python_busnr = 0;
-
-int __chrp python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-				    unsigned char offset, unsigned char *val)
-{
-	if (bus > python_busnr) {
-		*val = 0xff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
-	*val = in_8((unsigned char *)python_config_data(bus) + (offset&3));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int __chrp python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-				    unsigned char offset, unsigned short *val)
-{
-	if (bus > python_busnr) {
-		*val = 0xffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
-	*val = in_le16((unsigned short *)(python_config_data(bus) + (offset&3)));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-
-int __chrp python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-				     unsigned char offset, unsigned int *val)
-{
-	if (bus > python_busnr) {
-		*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
-	*val = in_le32((unsigned *)python_config_data(bus));
-	return PCIBIOS_SUCCESSFUL;
-}
 
-int __chrp python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-				     unsigned char offset, unsigned char val)
-{
-	if (bus > python_busnr)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
-	out_8((volatile unsigned char *)python_config_data(bus) + (offset&3), val);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int __chrp python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-				     unsigned char offset, unsigned short val)
-{
-	if (bus > python_busnr)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
-	out_le16((volatile unsigned short *)python_config_data(bus) + (offset&3),
-		 val);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int __chrp python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-				      unsigned char offset, unsigned int val)
-{
-	if (bus > python_busnr)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
-	out_le32((unsigned *)python_config_data(bus) + (offset&3), val);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-
-int __chrp rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-				    unsigned char offset, unsigned char *val)
-{
-	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
-	unsigned long ret;
-
-	if (call_rtas( "read-pci-config", 2, 2, &ret, addr, 1) != 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	*val = ret;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int __chrp rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-				    unsigned char offset, unsigned short *val)
-{
-	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
-	unsigned long ret;
-
-	if (call_rtas("read-pci-config", 2, 2, &ret, addr, 2) != 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	*val = ret;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-
-int __chrp rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-				     unsigned char offset, unsigned int *val)
-{
-	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
-	unsigned long ret;
-
-	if (call_rtas("read-pci-config", 2, 2, &ret, addr, 4) != 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	*val = ret;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int __chrp rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-				     unsigned char offset, unsigned char val)
-{
-	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
-	if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 1, (ulong)val ) != 0 )
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int __chrp rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-				     unsigned char offset, unsigned short val)
-{
-	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
-	if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 2, (ulong)val ) != 0 )
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	return PCIBIOS_SUCCESSFUL;
-}
+#define PYTHON_PCI_OP(rw, size, type, op, mask)			    	     \
+int __chrp								     \
+python_##rw##_config_##size(struct pci_dev *dev, int offset, type val) 	     \
+{									     \
+	struct pci_controller *hose = dev->sysdata;			     \
+									     \
+	out_be32(hose->cfg_addr,					     \
+		 PYTHON_CFA(dev->bus->number, dev->devfn, offset));	     \
+	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);   	     \
+	return PCIBIOS_SUCCESSFUL;					     \
+}
+
+PYTHON_PCI_OP(read, byte, u8 *, in_8, 3)
+PYTHON_PCI_OP(read, word, u16 *, in_le16, 2)
+PYTHON_PCI_OP(read, dword, u32 *, in_le32, 0)
+PYTHON_PCI_OP(write, byte, u8, out_8, 3)
+PYTHON_PCI_OP(write, word, u16, out_le16, 2)
+PYTHON_PCI_OP(write, dword, u32, out_le32, 0)
+
+static struct pci_ops python_pci_ops =
+{
+	python_read_config_byte,
+	python_read_config_word,
+	python_read_config_dword,
+	python_write_config_byte,
+	python_write_config_word,
+	python_write_config_dword
+};
 
-int __chrp rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-				      unsigned char offset, unsigned int val)
-{
-	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
-	if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 4, (ulong)val ) != 0 )
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	return PCIBIOS_SUCCESSFUL;
-}
+#ifdef CONFIG_POWER4
+/*
+ * Access functions for PCI config space using RTAS calls.
+ */
+#define RTAS_PCI_READ_OP(size, type, nbytes)			    	  \
+int __chrp								  \
+rtas_read_config_##size(struct pci_dev *dev, int offset, type val) 	  \
+{									  \
+	unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
+		| ((dev->bus->number & 0xff) << 16);			  \
+	unsigned long ret = ~0UL;					  \
+	int rval;							  \
+									  \
+	rval = call_rtas("read-pci-config", 2, 2, &ret, addr, nbytes);	  \
+	*val = ret;							  \
+	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;    	  \
+}
+
+#define RTAS_PCI_WRITE_OP(size, type, nbytes)				  \
+int __chrp								  \
+rtas_write_config_##size(struct pci_dev *dev, int offset, type val)	  \
+{									  \
+	unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
+		| ((dev->bus->number & 0xff) << 16);			  \
+	int rval;							  \
+									  \
+	rval = call_rtas("write-pci-config", 3, 1, NULL,		  \
+			 addr, nbytes, (ulong)val);			  \
+	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;	  \
+}
+
+RTAS_PCI_READ_OP(byte, u8 *, 1)
+RTAS_PCI_READ_OP(word, u16 *, 2)
+RTAS_PCI_READ_OP(dword, u32 *, 4)
+RTAS_PCI_WRITE_OP(byte, u8, 1)
+RTAS_PCI_WRITE_OP(word, u16, 2)
+RTAS_PCI_WRITE_OP(dword, u32, 4)
+
+static struct pci_ops rtas_pci_ops =
+{
+	rtas_read_config_byte,
+	rtas_read_config_word,
+	rtas_read_config_dword,
+	rtas_write_config_byte,
+	rtas_write_config_word,
+	rtas_write_config_dword
+};
+#endif /* CONFIG_POWER4 */
 
     /*
      *  Temporary fixes for PCI devices. These should be replaced by OF query
@@ -278,7 +203,7 @@
 					   HYDRA_FC_MPIC_ENABLE |
 					   HYDRA_FC_SLOW_SCC_PCLK |
 					   HYDRA_FC_MPIC_IS_MASTER));
-	OpenPIC = (volatile struct OpenPIC *)&Hydra->OpenPIC;
+	OpenPIC_Addr = &Hydra->OpenPIC;
 	OpenPIC_InitSenses = hydra_openpic_initsenses;
 	OpenPIC_NumInitSenses = sizeof(hydra_openpic_initsenses);
 	return 1;
@@ -316,54 +241,25 @@
 chrp_pcibios_fixup(void)
 {
 	struct pci_dev *dev;
-	int *brp;
 	struct device_node *np;
-	extern struct pci_ops generic_pci_ops;
-
-#ifndef CONFIG_POWER4
-	np = find_devices("device-tree");
-	if (np != 0) {
-		for (np = np->child; np != NULL; np = np->sibling) {
-			if (np->type == NULL || strcmp(np->type, "pci") != 0)
-				continue;
-			if ((brp = (int *) get_property(np, "bus-range", NULL)) == 0)
-				continue;
-			if (brp[0] != 0)	/* bus 0 is already done */
-				pci_scan_bus(brp[0], &generic_pci_ops, NULL);
-		}
-	}
-#else
-	/* XXX kludge for now because we can't properly handle
-	   physical addresses > 4GB.  -- paulus */
-	pci_scan_bus(0x1e, &generic_pci_ops, NULL);
-#endif /* CONFIG_POWER4 */
 
 	/* PCI interrupts are controlled by the OpenPIC */
 	pci_for_each_dev(dev) {
-		np = find_pci_device_OFnode(dev->bus->number, dev->devfn);
+		np = pci_device_to_OF_node(dev);
 		if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
 			dev->irq = np->intrs[0].line;
-		/* these need to be absolute addrs for OF and Matrox FB -- Cort */
-		if ( dev->vendor == PCI_VENDOR_ID_MATROX )
-		{
-			if ( dev->resource[0].start < isa_mem_base )
-				dev->resource[0].start += isa_mem_base;
-			if ( dev->resource[1].start < isa_mem_base )
-				dev->resource[1].start += isa_mem_base;
-		}
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+
 		/* the F50 identifies the amd as a trident */
 		if ( (dev->vendor == PCI_VENDOR_ID_TRIDENT) &&
 		      (dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET) )
 		{
 			dev->vendor = PCI_VENDOR_ID_AMD;
-			pcibios_write_config_word(dev->bus->number,
-			  dev->devfn, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
+			pci_write_config_word(dev, PCI_VENDOR_ID,
+					      PCI_VENDOR_ID_AMD);
 		}
 #ifdef CONFIG_POWER4
 		power4_fixup_dev(dev);
-#else
-		if (dev->bus->number > 0 && python_busnr > 0)
-			dev->resource[0].start += dev->bus->number*0x01000000;
 #endif
 	}
 }
@@ -402,86 +298,213 @@
     	bus->resource[1] = &gg2_resources.pci_mem;
 }
 
-decl_config_access_method(grackle);
-decl_config_access_method(indirect);
-decl_config_access_method(rtas);
+static void process_bridge_ranges(struct pci_controller *hose,
+				  struct device_node *dev, int index)
+{
+	unsigned int *ranges;
+	int rlen = 0;
+	int memno = 0;
+	struct resource *res;
+
+	hose->io_base_phys = 0;
+	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+	while ((rlen -= 6 * sizeof(unsigned int)) >= 0) {
+		res = NULL;
+		switch (ranges[0] >> 24) {
+		case 1:		/* I/O space */
+			if (ranges[2] != 0)
+				break;
+			hose->io_base_phys = ranges[3];
+			hose->io_base_virt = ioremap(ranges[3], ranges[5]);
+			if (index == 0) {
+				isa_io_base = (unsigned long) hose->io_base_virt;
+				printk("isa_io_base=%lx\n", isa_io_base);
+			}
+			res = &hose->io_resource;
+			res->flags = IORESOURCE_IO;
+			break;
+		case 2:		/* memory space */
+			if (index == 0 && ranges[1] == 0 && ranges[2] == 0){
+				isa_mem_base = ranges[3];
+				printk("isa_mem_base=%lx\n", isa_mem_base);
+			}
+			if (memno == 0) {
+				hose->pci_mem_offset = ranges[3] - ranges[2];
+				printk("pci_mem_offset=%lx for this bridge\n",
+				       hose->pci_mem_offset);
+			}
+			res = &hose->mem_resources[memno];
+			res->flags = IORESOURCE_MEM;
+			++memno;
+			break;
+		}
+		if (res != NULL) {
+			res->name = dev->full_name;
+			res->start = ranges[3];
+			res->end = res->start + ranges[5] - 1;
+			res->parent = NULL;
+			res->sibling = NULL;
+			res->child = NULL;
+		}
+		ranges += 6;
+	}
+}
+
+/* this is largely modeled and stolen after the pmac_pci code -- tgall
+ */
+
+static void __init
+ibm_add_bridges(struct device_node *dev)
+{
+	int *bus_range;
+	int len, index = 0;
+	struct pci_controller *hose;
+	volatile unsigned char *cfg;
+	unsigned int *dma;
+#ifdef CONFIG_POWER3
+	unsigned long *opprop = (unsigned long *)
+		get_property(find_path_device("/"), "platform-open-pic", NULL);
+#endif
+
+	for(; dev != NULL; dev = dev->next, ++index) {
+		if (dev->n_addrs < 1) {
+			printk(KERN_WARNING "Can't use %s: no address\n",
+			       dev->full_name);
+			continue;
+		}
+		bus_range = (int *) get_property(dev, "bus-range", &len);
+		if (bus_range == NULL || len < 2 * sizeof(int)) {
+			printk(KERN_WARNING "Can't get bus-range for %s\n",
+				dev->full_name);
+			continue;
+		}
+		if (bus_range[1] == bus_range[0])
+			printk(KERN_INFO "PCI bus %d", bus_range[0]);
+		else
+			printk(KERN_INFO "PCI buses %d..%d",
+			       bus_range[0], bus_range[1]);
+		printk(" controlled by %s at %x\n", dev->type,
+		       dev->addrs[0].address);
+
+		hose = pcibios_alloc_controller();
+		if (!hose) {
+			printk("Can't allocate PCI controller structure for %s\n",
+				dev->full_name);
+			continue;
+		}
+		hose->arch_data = dev;
+		hose->first_busno = bus_range[0];
+		hose->last_busno = bus_range[1];
+		hose->ops = &python_pci_ops;
+
+		cfg = ioremap(dev->addrs[0].address + 0xf8000, 0x20);
+       		hose->cfg_addr = (volatile unsigned int *) cfg;
+       		hose->cfg_data = cfg + 0x10;
+
+		process_bridge_ranges(hose, dev, index);
+
+#ifdef CONFIG_POWER3
+                openpic_setup_ISU(index, opprop[index+1]);
+#endif /* CONFIG_POWER3 */
+
+		/* check the first bridge for a property that we can
+		   use to set pci_dram_offset */
+		dma = (unsigned int *)
+			get_property(dev, "ibm,dma-ranges", &len);
+		if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
+			pci_dram_offset = dma[2] - dma[3];
+			printk("pci_dram_offset = %lx\n", pci_dram_offset);
+		}
+	}
+}
 
+#ifdef CONFIG_POWER4
 void __init
-chrp_setup_pci_ptrs(void)
+power4_add_bridge(void)
+{
+	struct pci_controller* hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	
+	hose->ops = &rtas_pci_ops;
+	pci_dram_offset = 0;
+}
+#endif /* CONFIG_POWER4 */
+
+void __init
+chrp_find_bridges(void)
 {
 	struct device_node *py;
+	char *model, *name;
+	struct pci_controller* hose;
 
 	ppc_md.pcibios_fixup = chrp_pcibios_fixup;
+
 #ifdef CONFIG_POWER4
-	set_config_access_method(rtas);
-	pci_dram_offset = 0;
+	power4_add_bridge();
 #else /* CONFIG_POWER4 */
-        if ( !strncmp("MOT",
-                      get_property(find_path_device("/"), "model", NULL),3) )
-        {
-                pci_dram_offset = 0;
-                isa_mem_base = 0xf7000000;
-                isa_io_base = 0xfe000000;
-                set_config_access_method(grackle);
+	model = get_property(find_path_device("/"), "model", NULL);
+        if (!strncmp("MOT", model, 3)) {
+		struct pci_controller* hose;
+
+		hose = pcibios_alloc_controller();
+		if (!hose)
+			return;
+		hose->first_busno = 0;
+		hose->last_busno = 0xff;
+        	/* Check that please. This must be the root of the OF
+        	 * PCI tree (the root host bridge
+        	 */
+               	hose->arch_data = find_devices("pci");
+                setup_grackle(hose, 0x20000);
+		return;
         }
-        else
-        {
-		if ((py = find_compatible_devices("pci", "IBM,python")) != 0
-		    || (py = find_compatible_devices("pci", "IBM,python3.0")) != 0)
-		{
-			char *name = get_property(find_path_device("/"), "name", NULL);
 
-			/* find out how many pythons */
-			while ( (py = py->next) ) python_busnr++;
-			set_config_access_method(python);
-
-			/*
-			 * We base these values on the machine type but should
-			 * try to read them from the python controller itself.
-			 * -- Cort
-			 */
-			if ( !strncmp("IBM,7025-F50", name, 12) )
-			{
-				pci_dram_offset = 0x80000000;
-				isa_mem_base = 0xa0000000;
-				isa_io_base = 0x88000000;
-			} else if ( !strncmp("IBM,7043-260", name, 12)
-				    || !strncmp("IBM,7044-270", name, 12))
-			{
-				pci_dram_offset = 0x0;
-				isa_mem_base = 0xc0000000;
-				isa_io_base = 0xf8000000;
-			}
-                }
-                else
-                {
-			if ( !strncmp("IBM,7043-150", get_property(find_path_device("/"), "name", NULL),12) ||
-			     !strncmp("IBM,7046-155", get_property(find_path_device("/"), "name", NULL),12) ||
-			     !strncmp("IBM,7046-B50", get_property(find_path_device("/"), "name", NULL),12) )
-			{
-				pci_dram_offset = 0;
-				isa_mem_base = 0x80000000;
-				isa_io_base = 0xfe000000;
-				pci_config_address = (unsigned int *)0xfec00000;
-				pci_config_data = (unsigned char *)0xfee00000;
-				set_config_access_method(indirect);
-			}
-			else
-			{
-				/* LongTrail */
-				pci_dram_offset = 0;
-				isa_mem_base = 0xf7000000;
-				isa_io_base = 0xf8000000;
-				set_config_access_method(gg2);
-				ppc_md.pcibios_fixup = gg2_pcibios_fixup;
-				ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus;
-			}
-                }
-        }
+	if ((py = find_compatible_devices("pci", "IBM,python")))
+	{
+		/* XXX xmon_init_scc needs this set and the BAT
+		   set up in MMU_init */
+		ibm_add_bridges(find_devices("pci"));
+		return;
+	}
+
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	/* Check that please. This must be the root of the OF
+	 * PCI tree (the root host bridge
+	 */
+	hose->arch_data = find_devices("pci");
+	name = get_property(find_path_device("/"), "name", NULL);
+	if (!strncmp("IBM,7043-150", name, 12) ||
+	    !strncmp("IBM,7046-155", name, 12) ||
+	    !strncmp("IBM,7046-B50", name, 12) ) {
+		setup_grackle(hose, 0x01000000);
+		isa_mem_base = 0x80000000;
+		return;
+	}
+
+	/* LongTrail */
+	hose->ops = &gg2_pci_ops;
+	pci_dram_offset = 0;
+	isa_mem_base = 0xf7000000;
+	hose->io_base_phys = (unsigned long) 0xf8000000;
+	hose->io_base_virt = ioremap(hose->io_base_phys, 0x10000);
+	isa_io_base = (unsigned long) hose->io_base_virt;
+	ppc_md.pcibios_fixup = gg2_pcibios_fixup;
+	ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus;
 #endif /* CONFIG_POWER4 */
 }
 
 #ifdef CONFIG_PPC64BRIDGE
+#ifdef CONFIG_POWER4
 /*
  * Hack alert!!!
  * 64-bit machines like POWER3 and POWER4 have > 32 bit
@@ -490,9 +513,7 @@
  * page table gives us into parts of the physical address
  * space above 4GB so we can access the I/O devices.
  */
-
-#ifdef CONFIG_POWER4
-static unsigned long pci_address_offset(int busnr, unsigned int flags)
+unsigned long pci_address_offset(int busnr, unsigned int flags)
 {
 	unsigned long offset = 0;
 
@@ -507,35 +528,6 @@
 		else
 	}
 	return offset;
-}
-
-unsigned long phys_to_bus(unsigned long pa)
-{
-	if (pa >= 0xf8000000)
-		pa -= 0x38000000;
-	else if (pa >= 0x80000000 && pa < 0xc0000000)
-		pa += 0x40000000;
-	return pa;
-}
-
-unsigned long bus_to_phys(unsigned int ba, int busnr)
-{
-	return ba + pci_address_offset(busnr, IORESOURCE_MEM);
-}
-
-#else /* CONFIG_POWER4 */
-/*
- * For now assume I/O addresses are < 4GB and PCI bridges don't
- * remap addresses on POWER3 machines.
- */
-unsigned long phys_to_bus(unsigned long pa)
-{
-	return pa;
-}
-
-unsigned long bus_to_phys(unsigned int ba, int busnr)
-{
-	return ba;
 }
 #endif /* CONFIG_POWER4 */
 #endif /* CONFIG_PPC64BRIDGE */
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.4.0/linux/arch/ppc/kernel/chrp_setup.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/kernel/chrp_setup.c	Mon Jan 22 15:41:15 2001
@@ -30,7 +30,6 @@
 #include <linux/ioport.h>
 #include <linux/console.h>
 #include <linux/pci.h>
-#include <linux/openpic.h>
 #include <linux/version.h>
 #include <linux/adb.h>
 #include <linux/module.h>
@@ -50,21 +49,19 @@
 #include <asm/hydra.h>
 #include <asm/keyboard.h>
 #include <asm/init.h>
-
 #include <asm/time.h>
+
 #include "local_irq.h"
 #include "i8259.h"
 #include "open_pic.h"
 #include "xics.h"
 
-extern volatile unsigned char *chrp_int_ack_special;
-
 unsigned long chrp_get_rtc_time(void);
 int chrp_set_rtc_time(unsigned long nowtime);
 void chrp_calibrate_decr(void);
 long chrp_time_init(void);
 
-void chrp_setup_pci_ptrs(void);
+void chrp_find_bridges(void);
 void chrp_event_scan(void);
 void rtas_display_progress(char *, unsigned short);
 void rtas_indicator_progress(char *, unsigned short);
@@ -92,7 +89,7 @@
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 extern int probingmem;
-extern unsigned long loops_per_sec;
+extern unsigned long loops_per_jiffy;
 extern int bootx_text_mapped;
 static int max_width;
 
@@ -244,7 +241,7 @@
 	struct device_node *device;
 
 	/* init to some ~sane value until calibrate_delay() runs */
-	loops_per_sec = 50000000;
+	loops_per_jiffy = 50000000/HZ;
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* this is fine for chrp */
@@ -257,6 +254,9 @@
 		ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
 	printk("Boot arguments: %s\n", cmd_line);
 
+	/* Lookup PCI host bridges */
+	chrp_find_bridges();
+
 #ifndef CONFIG_PPC64BRIDGE
 	/* PCI bridge config space access area -
 	 * appears to be not in devtree on longtrail. */
@@ -266,11 +266,12 @@
 	 *  -- Geert
 	 */
 	hydra_init();		/* Mac I/O */
+
 #endif /* CONFIG_PPC64BRIDGE */
 
 #ifndef CONFIG_POWER4
 	/* Some IBM machines don't have the hydra -- Cort */
-	if ( !OpenPIC )
+	if ( !OpenPIC_Addr )
 	{
 		unsigned long *opprop;
 
@@ -279,7 +280,7 @@
 		if (opprop != 0) {
 			printk("OpenPIC addrs: %lx %lx %lx\n",
 			       opprop[0], opprop[1], opprop[2]);
-			OpenPIC = ioremap(opprop[0], sizeof(struct OpenPIC));
+			OpenPIC_Addr = ioremap(opprop[0], 0x40000);
 		}
 	}
 #endif
@@ -292,23 +293,17 @@
 	conswitchp = &dummy_con;
 #endif
 
-#ifndef CONFIG_PPC64BRIDGE
-	pmac_find_bridges();
-#endif /* CONFIG_PPC64BRIDGE */
-
 	/* Get the event scan rate for the rtas so we know how
 	 * often it expects a heartbeat. -- Cort
 	 */
-	if ( rtas_data )
-	{
+	if ( rtas_data ) {
 		struct property *p;
 		device = find_devices("rtas");
 		for ( p = device->properties;
 		      p && strncmp(p->name, "rtas-event-scan-rate", 20);
 		      p = p->next )
 			/* nothing */ ;
-		if ( p && *(unsigned long *)p->value )
-		{
+		if ( p && *(unsigned long *)p->value ) {
 			ppc_md.heartbeat = chrp_event_scan;
 			ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
 			ppc_md.heartbeat_count = 1;
@@ -365,79 +360,44 @@
 	}
 }
 
-int __chrp chrp_get_irq( struct pt_regs *regs )
-{
-        int irq;
-
-        irq = openpic_irq( smp_processor_id() );
-        if (irq == IRQ_8259_CASCADE)
-        {
-                /*
-                 * This magic address generates a PCI IACK cycle.
-                 */
-		if ( chrp_int_ack_special )
-			irq = *chrp_int_ack_special;
-		else
-			irq = i8259_irq( smp_processor_id() );
-		openpic_eoi( smp_processor_id() );
-        }
-        if (irq == OPENPIC_VEC_SPURIOUS)
-                /*
-                 * Spurious interrupts should never be
-                 * acknowledged
-                 */
-		irq = -1;
-	/*
-	 * I would like to openpic_eoi here but there seem to be timing problems
-	 * between the openpic ack and the openpic eoi.
-	 *   -- Cort
-	 */
-	return irq;
-}
-
-void __chrp chrp_post_irq(struct pt_regs* regs, int irq)
-{
-	/*
-	 * If it's an i8259 irq then we've already done the
-	 * openpic irq.  So we just check to make sure the controller
-	 * is an openpic and if it is then eoi
-	 *
-	 * We do it this way since our irq_desc[irq].handler can change
-	 * with RTL and no longer be open_pic -- Cort
-	 */
-	if ( irq >= open_pic_irq_offset)
-		openpic_eoi( smp_processor_id() );
-}
-
 void __init chrp_init_IRQ(void)
 {
 	struct device_node *np;
 	int i;
 	unsigned long *addrp;
+	unsigned char* chrp_int_ack_special = 0;
+	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
+	int nmi_irq = -1;
+#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)	
+	struct device_node *kbd;
+#endif
 
 	if (!(np = find_devices("pci"))
 	    || !(addrp = (unsigned long *)
 		 get_property(np, "8259-interrupt-acknowledge", NULL)))
 		printk("Cannot find pci to get ack address\n");
 	else
-		chrp_int_ack_special = (volatile unsigned char *)
-			ioremap(*addrp, 1);
-	open_pic_irq_offset = 16;
-	for ( i = 16 ; i < NR_IRQS ; i++ )
-		irq_desc[i].handler = &open_pic;
-	openpic_init(1);
-	enable_irq(IRQ_8259_CASCADE);
-	for ( i = 0 ; i < 16  ; i++ )
+		chrp_int_ack_special = (unsigned char *)ioremap(*addrp, 1);
+	/* hydra still sets OpenPIC_InitSenses to a static set of values */
+	if (OpenPIC_InitSenses == NULL) {
+		prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
+		OpenPIC_InitSenses = init_senses;
+		OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
+	}
+	openpic_init(1, NUM_8259_INTERRUPTS, chrp_int_ack_special, nmi_irq);
+	for ( i = 0 ; i < NUM_8259_INTERRUPTS  ; i++ )
 		irq_desc[i].handler = &i8259_pic;
 	i8259_init();
-#ifdef CONFIG_XMON
-	request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI),
-		    xmon_irq, 0, "NMI", 0);
-#endif	/* CONFIG_XMON */
-#ifdef CONFIG_SMP
-	request_irq(openpic_to_irq(OPENPIC_VEC_IPI),
-		    openpic_ipi_action, 0, "IPI0", 0);
-#endif	/* CONFIG_SMP */
+#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
+	/* see if there is a keyboard in the device tree
+	   with a parent of type "adb" */
+	for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
+		if (kbd->parent && kbd->parent->type
+		    && strcmp(kbd->parent->type, "adb") == 0)
+			break;
+	if (kbd)
+		request_irq( HYDRA_INT_ADB_NMI, xmon_irq, 0, "XMON break", 0);
+#endif
 }
 
 void __init
@@ -556,12 +516,6 @@
 }
 
 void __chrp
-chrp_ide_fix_driveid(struct hd_driveid *id)
-{
-        ppc_generic_ide_fix_driveid(id);
-}
-
-void __chrp
 chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
 	ide_ioreg_t reg = data_port;
@@ -586,7 +540,6 @@
 	   chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
 		     unsigned long r6, unsigned long r7)
 {
-	chrp_setup_pci_ptrs();
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* take care of initrd if we have one */
 	if ( r6 )
@@ -596,10 +549,10 @@
 	}
 #endif /* CONFIG_BLK_DEV_INITRD */
 
-        /* pci_dram_offset/isa_io_base/isa_mem_base set by setup_pci_ptrs() */
 	ISA_DMA_THRESHOLD = ~0L;
 	DMA_MODE_READ = 0x44;
 	DMA_MODE_WRITE = 0x48;
+	isa_io_base = CHRP_ISA_IO_BASE;		/* default value */
 
 	ppc_md.setup_arch     = chrp_setup_arch;
 	ppc_md.setup_residual = NULL;
@@ -607,8 +560,8 @@
 	ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
 #ifndef CONFIG_POWER4
 	ppc_md.init_IRQ       = chrp_init_IRQ;
-	ppc_md.get_irq        = chrp_get_irq;
-	ppc_md.post_irq	      = chrp_post_irq;
+	ppc_md.get_irq        = openpic_get_irq;
+	ppc_md.post_irq	      = NULL;
 #else
 	ppc_md.init_IRQ	      = xics_init_IRQ;
 	ppc_md.get_irq	      = xics_get_irq;
@@ -669,11 +622,12 @@
         ppc_ide_md.ide_check_region = chrp_ide_check_region;
         ppc_ide_md.ide_request_region = chrp_ide_request_region;
         ppc_ide_md.ide_release_region = chrp_ide_release_region;
-        ppc_ide_md.fix_driveid = chrp_ide_fix_driveid;
+        ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid;
         ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;
 
         ppc_ide_md.io_base = _IO_BASE;
 #endif
+
 	/*
 	 * Print the banner, then scroll down so boot progress
 	 * can be printed.  -- Cort 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- v2.4.0/linux/arch/ppc/kernel/entry.S	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/kernel/entry.S	Mon Jan 22 15:41:15 2001
@@ -234,7 +234,6 @@
 	li	r0,0x0ff0
 	stw	r0,TRAP(r1)
 	stw	r1,KSP(r3)	/* Set old stack pointer */
-	sync
 	tophys(r0,r4)
 	CLR_TOP32(r0)
 	mtspr	SPRG3,r0	/* Update current THREAD phys addr */
@@ -251,7 +250,7 @@
 #endif
         mtspr   M_TWB,r9	/* Update MMU base address */
 	tlbia
-	SYNC
+	sync
 #endif /* CONFIG_8xx */
 	lwz	r1,KSP(r4)	/* Load new stack pointer */
 	/* save the old current 'last' for return value */
@@ -342,23 +341,23 @@
 do_bottom_half_ret:
 2:	lwz	r3,_MSR(r1)	/* Returning to user mode? */
 	andi.	r3,r3,MSR_PR
-	beq+	restore		/* if so, check need_resched and signals */
-	.globl ret_to_user_hook	
-ret_to_user_hook:
-	nop
+	beq+	do_signal_ret	/* if so, check need_resched and signals */
 	lwz	r3,NEED_RESCHED(r2)
 	cmpi	0,r3,0		/* check need_resched flag */
 	beq+	7f
 	bl	schedule
 7:	lwz	r5,SIGPENDING(r2) /* Check for pending unblocked signals */
 	cmpwi	0,r5,0
-	beq+	restore
+	beq+	do_signal_ret
 	li	r3,0
 	addi	r4,r1,STACK_FRAME_OVERHEAD
 	MOL_HOOK_MMU(8,r8)
 	bl	do_signal
 	.globl	do_signal_ret
 do_signal_ret:
+	.globl ret_to_user_hook	
+ret_to_user_hook:
+	nop
 restore:
 	lwz	r3,_XER(r1)
 	mtspr	XER,r3
@@ -372,7 +371,7 @@
 	 */
 	mfmsr	r0		/* Get current interrupt state */
 	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
-	sync			/* Some chip revs have problems here... */
+	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0		/* Update machine state */
 	
 	/* if returning to user mode, set new sprg2 and save kernel SP */
@@ -468,7 +467,7 @@
 	andc	r0,r9,r0
 	li	r10,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP
 	andc	r9,r0,r10
-	sync			/* disable interrupts so SRR0/1 */
+	SYNC			/* disable interrupts so SRR0/1 */
 	mtmsr	r0		/* don't get trashed */
 	mtlr	r6
 	CLR_TOP32(r7)
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/error_log.c linux/arch/ppc/kernel/error_log.c
--- v2.4.0/linux/arch/ppc/kernel/error_log.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/error_log.c	Mon Jan 22 15:41:15 2001
@@ -0,0 +1,183 @@
+/*
+ *  arch/ppc/kernel/error_log.c
+ *  
+ *  Copyright (c) 2000 Tilmann Bitterberg
+ *  (tilmann@bitterberg.de)
+ *
+ *  Error processing of errors found by rtas even-scan routine
+ *  which is done with every heartbeat. (chrp_setup.c)
+ */
+
+#include <linux/sched.h>
+
+#include <asm/prom.h>
+
+#include "error_log.h"
+
+/* ****************************************************************** */
+/* 
+ * EVENT-SCAN
+ * The whole stuff below here doesn't take any action when it found
+ * an error, it just prints as much information as possible and 
+ * then its up to the user to decide what to do.
+ *
+ * Returns 0 if no errors were found
+ * Returns 1 if there may be more errors
+ */
+int ppc_rtas_errorlog_scan(void)
+{
+const char *_errlog_severity[] = {
+#ifdef VERBOSE_ERRORS
+	"No Error\n\t\
+Should require no further information",
+	"Event\n\t\
+This is not really an error, it is an event. I use events\n\t\
+to communicate with RTAS back and forth.",
+	"Warning\n\t\
+Indicates a non-state-losing error, either fully recovered\n\t\
+by RTAS or not needing recovery. Ignore it.",
+	"Error sync\n\t\
+May only be fatal to a certain program or thread. Recovery\n\t\
+and continuation is possible, if I only had a handler for\n\t\
+this. Less serious",
+	"Error\n\t\
+Less serious, but still causing a loss of data and state.\n\t\
+I can't tell you exactly what to do, You have to decide\n\t\
+with help from the target and initiator field, what kind\n\t\
+of further actions may take place.",
+	"Fatal\n\t\
+Represent a permanent hardware failure and I believe this\n\t\
+affects my overall performance and behaviour. I would not\n\t\
+attempt to continue normal operation."
+#else
+	"No Error",
+	"Event",
+	"Warning",
+	"Error sync",
+	"Error",
+	"Fatal"
+#endif /* VERBOSE_ERRORS */
+};
+
+#if 0 /* unused?? */
+const char *_errlog_disposition[] = {
+#ifdef VERBOSE_ERRORS
+	"Fully recovered\n\t\
+There was an error, but it is fully recovered by RTAS.",
+	"Limited recovery\n\t\
+RTAS was able to recover the state of the machine, but some\n\t\
+feature of the machine has been disabled or lost (for example\n\t\
+error checking) or performance may suffer.",
+	"Not recovered\n\t\
+Whether RTAS did not try to recover anything or recovery failed:\n\t\
+HOUSTON, WE HAVE A PROBLEM!"
+#else
+	"Fully recovered",
+	"Limited recovery",
+	"Not recovered"
+#endif /* VERBOSE_ERRORS */
+};
+#endif
+
+const char *_errlog_extended[] = {
+#ifdef VERBOSE_ERRORS
+	"Not present\n\t\
+Sad, the RTAS call didn't return an extended error log.",
+	"Present\n\t\
+The extended log is present and hopefully it contains a lot of\n\t\
+useful information, which leads to the solution of the problem."
+#else
+	"Not present",
+	"Present"
+#endif /* VERBOSE_ERRORS */
+};
+
+const char *_errlog_initiator[] = { 
+	"Unknown or not applicable",
+	"CPU",
+	"PCI",
+	"ISA",
+	"Memory",
+	"Power management"
+};
+
+const char *_errlog_target[] = { 
+	"Unknown or not applicable",
+	"CPU",
+	"PCI",
+	"ISA",
+	"Memory",
+	"Power management"
+};
+	rtas_error_log error_log;
+	char logdata[1024];
+	int error;
+#if 0 /* unused?? */
+	int retries = 0; /* if HW error, try 10 times */
+#endif
+
+	error = call_rtas ("event-scan", 4, 1, (unsigned long *)&error_log,
+			INTERNAL_ERROR | EPOW_WARNING,
+			0, __pa(logdata), 1024);
+
+	if (error == 1) /* no errors found */
+		return 0;
+
+	if (error == -1) {
+		printk(KERN_ERR "Unable to get errors. Do you a favor and throw this box away\n");
+		return 0;
+	}
+	if (error_log.version != 1)
+		printk(KERN_WARNING "Unknown version (%d), please implement me\n", 
+				error_log.version);
+
+	switch (error_log.disposition) {
+		case DISP_FULLY_RECOVERED:
+			/* there was an error, but everything is fine now */
+			return 0;
+		case DISP_NOT_RECOVERED:
+			printk("We have a really serious Problem!\n");
+		case DISP_LIMITED_RECOVERY:
+			printk("Error classification\n");
+			printk("Severity  : %s\n", 
+					ppc_rtas_errorlog_check_severity (error_log));
+			printk("Initiator : %s\n", 
+					ppc_rtas_errorlog_check_initiator (error_log));
+			printk("Target    : %s\n", 
+					ppc_rtas_errorlog_check_target (error_log));
+			printk("Type      : %s\n", 
+					ppc_rtas_errorlog_check_type (error_log));
+			printk("Ext. log  : %s\n", 
+					ppc_rtas_errorlog_check_extended (error_log));
+			if (error_log.extended)
+				ppc_rtas_errorlog_disect_extended (logdata);
+			return 1;	
+		default:
+			/* nothing */
+			break;
+	}
+	return 0;
+}
+/* ****************************************************************** */
+const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log)
+{
+	const char *_errlog_type[] = {
+		"unknown type",
+		"too many tries failed",
+		"TCE error",
+		"RTAS device failed",
+		"target timed out",
+		"parity error on data",			/* 5 */
+		"parity error on address",
+		"parity error on external cache",
+		"access to invalid address",
+		"uncorrectable ECC error",
+		"corrected ECC error"			/* 10 */
+	};
+	if (error_log.type == TYPE_EPOW) 
+		return "EPOW"; 
+	if (error_log.type >= TYPE_PMGM_POWER_SW_ON)
+		return "PowerMGM Event (not handled right now)";
+	return _errlog_type[error_log.type];
+}
+
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/error_log.h linux/arch/ppc/kernel/error_log.h
--- v2.4.0/linux/arch/ppc/kernel/error_log.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/error_log.h	Mon Jan 22 15:41:15 2001
@@ -0,0 +1,95 @@
+#ifndef __ERROR_LOG_H__
+#define __ERROR_LOG_H__
+
+#define VERBOSE_ERRORS		1 /* Maybe I enlarge the kernel too much */
+#undef VERBOSE_ERRORS
+
+/* Event classes */
+/* XXX: Endianess correct? NOW*/
+#define INTERNAL_ERROR		0x80000000 /* set bit 0 */
+#define EPOW_WARNING		0x40000000 /* set bit 1 */
+#define POWERMGM_EVENTS		0x20000000 /* set bit 2 */
+
+/* event-scan returns */
+#define SEVERITY_FATAL		0x5
+#define SEVERITY_ERROR		0x4
+#define SEVERITY_ERROR_SYNC	0x3
+#define SEVERITY_WARNING	0x2
+#define SEVERITY_EVENT		0x1
+#define SEVERITY_NO_ERROR	0x0
+#define DISP_FULLY_RECOVERED	0x0
+#define DISP_LIMITED_RECOVERY	0x1
+#define DISP_NOT_RECOVERED	0x2
+#define PART_PRESENT		0x0
+#define PART_NOT_PRESENT	0x1
+#define INITIATOR_UNKNOWN	0x0
+#define INITIATOR_CPU		0x1
+#define INITIATOR_PCI		0x2
+#define INITIATOR_ISA		0x3
+#define INITIATOR_MEMORY	0x4
+#define INITIATOR_POWERMGM	0x5
+#define TARGET_UNKNOWN		0x0
+#define TARGET_CPU		0x1
+#define TARGET_PCI		0x2
+#define TARGET_ISA		0x3
+#define TARGET_MEMORY		0x4
+#define TARGET_POWERMGM		0x5
+#define TYPE_RETRY		0x01
+#define TYPE_TCE_ERR		0x02
+#define TYPE_INTERN_DEV_FAIL	0x03
+#define TYPE_TIMEOUT		0x04
+#define TYPE_DATA_PARITY	0x05
+#define TYPE_ADDR_PARITY	0x06
+#define TYPE_CACHE_PARITY	0x07
+#define TYPE_ADDR_INVALID	0x08
+#define TYPE_ECC_UNCORR		0x09
+#define TYPE_ECC_CORR		0x0a
+#define TYPE_EPOW		0x40
+/* I don't add PowerMGM events right now, this is a different topic */ 
+#define TYPE_PMGM_POWER_SW_ON	0x60
+#define TYPE_PMGM_POWER_SW_OFF	0x61
+#define TYPE_PMGM_LID_OPEN	0x62
+#define TYPE_PMGM_LID_CLOSE	0x63
+#define TYPE_PMGM_SLEEP_BTN	0x64
+#define TYPE_PMGM_WAKE_BTN	0x65
+#define TYPE_PMGM_BATTERY_WARN	0x66
+#define TYPE_PMGM_BATTERY_CRIT	0x67
+#define TYPE_PMGM_SWITCH_TO_BAT	0x68
+#define TYPE_PMGM_SWITCH_TO_AC	0x69
+#define TYPE_PMGM_KBD_OR_MOUSE	0x6a
+#define TYPE_PMGM_ENCLOS_OPEN	0x6b
+#define TYPE_PMGM_ENCLOS_CLOSED	0x6c
+#define TYPE_PMGM_RING_INDICATE	0x6d
+#define TYPE_PMGM_LAN_ATTENTION	0x6e
+#define TYPE_PMGM_TIME_ALARM	0x6f
+#define TYPE_PMGM_CONFIG_CHANGE	0x70
+#define TYPE_PMGM_SERVICE_PROC	0x71
+
+typedef struct _rtas_error_log {
+	unsigned long version:8;		/* Architectural version */
+	unsigned long severity:3;		/* Severity level of error */
+	unsigned long disposition:2;		/* Degree of recovery */
+	unsigned long extended:1;		/* extended log present? */
+	unsigned long /* reserved */ :2;	/* Reserved for future use */
+	unsigned long initiator:4;		/* Initiator of event */
+	unsigned long target:4;			/* Target of failed operation */
+	unsigned long type:8;			/* General event or error*/
+	unsigned long extended_log_length:32;	/* length in bytes */
+} rtas_error_log;
+
+/* ****************************************************************** */
+#define ppc_rtas_errorlog_check_severity(x) \
+	(_errlog_severity[x.severity])
+#define ppc_rtas_errorlog_check_target(x) \
+	(_errlog_target[x.target])
+#define ppc_rtas_errorlog_check_initiator(x) \
+	(_errlog_initiator[x.initiator])
+#define ppc_rtas_errorlog_check_extended(x) \
+	(_errlog_extended[x.extended])
+#define ppc_rtas_errorlog_disect_extended(x) \
+	do { /* implement me */ } while(0)
+extern const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log);
+extern int ppc_rtas_errorlog_scan(void);
+
+
+#endif /* __ERROR_LOG_H__ */
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c
--- v2.4.0/linux/arch/ppc/kernel/feature.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/kernel/feature.c	Mon Jan 22 15:41:15 2001
@@ -238,12 +238,15 @@
 static struct feature_controller*
 feature_lookup_controller(struct device_node *device);
 
+#ifdef CONFIG_PMAC_PBOOK
 static void heathrow_prepare_for_sleep(struct feature_controller* ctrler);
 static void heathrow_wakeup(struct feature_controller* ctrler);
-static void keylargo_init(void);
-static void uninorth_init(void);
 static void core99_prepare_for_sleep(struct feature_controller* ctrler);
 static void core99_wake_up(struct feature_controller* ctrler);
+#endif /* CONFIG_PMAC_PBOOK */
+
+static void keylargo_init(void);
+static void uninorth_init(void);
 
 /* static variables */
 static struct feature_controller	controllers[MAX_FEATURE_CONTROLLERS];
@@ -255,6 +258,10 @@
 static int				uninorth_rev;
 static int				keylargo_rev;
 
+/*
+ * WARNING ! This function is called early in setup_arch, neither the IO base
+ * nor the udelay calibration have been done yet
+ */
 void
 feature_init(void)
 {
@@ -527,14 +534,31 @@
 void 
 feature_set_firewire_power(struct device_node* device, int power)
 {
+	if (!uninorth_base)
+		return;
+	if (power)
+		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
+	else
+		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
+	udelay(20);
+}
+
+#ifdef CONFIG_SMP
+void
+feature_core99_kick_cpu1(void)
+{
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_KICK_CPU1), KL_GPIO_KICK_CPU1_UP);
+	udelay(1);
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_KICK_CPU1), KL_GPIO_KICK_CPU1_DOWN);
 }
+#endif /* CONFIG_SMP */
 
 /* Initialize the Core99 UniNorth host bridge and memory controller
  */
 static void
 uninorth_init(void)
 {
-	struct device_node* gmac;
+	struct device_node* gmac, *fw;
 	unsigned long actrl;
 	
 	/* Set the arbitrer QAck delay according to what Apple does
@@ -564,6 +588,11 @@
 	}
 	if (gmac)
 		feature_set_gmac_power(gmac, 0);
+
+	/* Kludge (enable FW before PCI probe) */
+	fw = find_devices("firewire");
+	if (fw && device_is_compatible(fw, "pci106b,18"))
+		feature_set_firewire_power(fw, 1);
 }
 
 /* Initialize the Core99 KeyLargo ASIC. Currently, we just make sure
@@ -576,6 +605,43 @@
 }
 
 #ifdef CONFIG_PMAC_PBOOK
+
+static u32 save_fcr[5];
+static u32 save_mbcr;
+
+static void
+heathrow_prepare_for_sleep(struct feature_controller* ctrler)
+{
+	save_mbcr = in_le32(FREG(ctrler, 0x34));
+	save_fcr[0] = in_le32(FREG(ctrler, 0x38));
+	save_fcr[1] = in_le32(FREG(ctrler, 0x3c));
+
+	out_le32(FREG(ctrler, 0x38), save_fcr[0] & ~HRW_IOBUS_ENABLE);
+}
+
+static void
+heathrow_wakeup(struct feature_controller* ctrler)
+{
+	out_le32(FREG(ctrler, 0x38), save_fcr[0]);
+	out_le32(FREG(ctrler, 0x3c), save_fcr[1]);
+	out_le32(FREG(ctrler, 0x34), save_mbcr);
+	mdelay(1);
+	out_le32(FREG(ctrler, 0x38), save_fcr[0] | HRW_IOBUS_ENABLE);
+	mdelay(1);
+}
+
+static void
+core99_prepare_for_sleep(struct feature_controller* ctrler)
+{
+	/* Not yet implemented */
+}
+
+static void
+core99_wake_up(struct feature_controller* ctrler)
+{
+	/* Not yet implemented */
+}
+
 void
 feature_prepare_for_sleep(void)
 {
@@ -599,7 +665,6 @@
 	}
 }
 
-
 void
 feature_wake_up(void)
 {
@@ -622,39 +687,4 @@
 	}
 }
 
-static u32 save_fcr[5];
-static u32 save_mbcr;
-
-static void
-heathrow_prepare_for_sleep(struct feature_controller* ctrler)
-{
-	save_mbcr = in_le32(FREG(ctrler, 0x34));
-	save_fcr[0] = in_le32(FREG(ctrler, 0x38));
-	save_fcr[1] = in_le32(FREG(ctrler, 0x3c));
-
-	out_le32(FREG(ctrler, 0x38), save_fcr[0] & ~HRW_IOBUS_ENABLE);
-}
-
-static void
-heathrow_wakeup(struct feature_controller* ctrler)
-{
-	out_le32(FREG(ctrler, 0x38), save_fcr[0]);
-	out_le32(FREG(ctrler, 0x3c), save_fcr[1]);
-	out_le32(FREG(ctrler, 0x34), save_mbcr);
-	mdelay(1);
-	out_le32(FREG(ctrler, 0x38), save_fcr[0] | HRW_IOBUS_ENABLE);
-	mdelay(1);
-}
-
-static void
-core99_prepare_for_sleep(struct feature_controller* ctrler)
-{
-	/* Not yet implemented */
-}
-
-static void
-core99_wake_up(struct feature_controller* ctrler)
-{
-	/* Not yet implemented */
-}
 #endif /* CONFIG_PMAC_PBOOK */
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/galaxy_pci.c linux/arch/ppc/kernel/galaxy_pci.c
--- v2.4.0/linux/arch/ppc/kernel/galaxy_pci.c	Thu Feb 10 12:37:51 2000
+++ linux/arch/ppc/kernel/galaxy_pci.c	Mon Jan 22 15:41:15 2001
@@ -36,67 +36,84 @@
 
 /* Function Prototypes */
 
-decl_config_access_method(galaxy);
-
-
 void __init
 galaxy_pcibios_fixup(void)
 {
 
 }
 
-void __init
-galaxy_setup_pci_ptrs(void)
+static int
+galaxy_pcibios_read_config_byte(struct pci_controller* hose,
+				  u8 bus, u8 dev, u8 offset, u8 *val)
 {
-	set_config_access_method(galaxy);
 
-	ppc_md.pcibios_fixup = galaxy_pcibios_fixup;
+	return (PCIBIOS_SUCCESSFUL);
 }
 
-int
-galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-				unsigned char offset, unsigned char *val)
+static int
+galaxy_pcibios_read_config_word(struct pci_controller* hose,
+				  u8 bus, u8 dev, u8 offset, u16 *val)
 {
 
 	return (PCIBIOS_SUCCESSFUL);
 }
 
-int
-galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-				unsigned char offset, unsigned short *val)
+static int
+galaxy_pcibios_read_config_dword(struct pci_controller* hose,
+				  u8 bus, u8 dev, u8 offset, u32 *val)
 {
 
 	return (PCIBIOS_SUCCESSFUL);
 }
 
-int
-galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-				 unsigned char offset, unsigned int *val)
+static int
+galaxy_pcibios_write_config_byte(struct pci_controller* hose,
+				  u8 bus, u8 dev, u8 offset, u8 val)
 {
 
 	return (PCIBIOS_SUCCESSFUL);
 }
 
-int
-galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-				 unsigned char offset, unsigned char val)
+static int
+galaxy_pcibios_write_config_word(struct pci_controller* hose,
+				  u8 bus, u8 dev, u8 offset, u16 val)
 {
 
 	return (PCIBIOS_SUCCESSFUL);
 }
 
-int
-galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-				 unsigned char offset, unsigned short val)
+static int
+galaxy_pcibios_write_config_dword(struct pci_controller* hose,
+				  u8 bus, u8 dev, u8 offset, u32 val)
 {
 
 	return (PCIBIOS_SUCCESSFUL);
 }
 
-int
-galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned int val)
+static struct pci_controller_ops galaxy_pci_ops =
 {
+	galaxy_pcibios_read_config_byte,
+	galaxy_pcibios_read_config_word,
+	galaxy_pcibios_read_config_dword,
+	galaxy_pcibios_write_config_byte,
+	galaxy_pcibios_write_config_word,
+	galaxy_pcibios_write_config_dword
+};
 
-	return (PCIBIOS_SUCCESSFUL);
+void __init
+galaxy_find_bridges(void)
+{
+	struct pci_controller* hose;
+
+	set_config_access_method(galaxy);
+
+	ppc_md.pcibios_fixup = galaxy_pcibios_fixup;
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+	hose->ops = &galaxy_pci_ops;
+	/* Todo ...
+	hose->cfg_data = ioremap(PCICFGDATA, ...);
+	hose->cfg_addr = ioremap(PCICFGADDR, ...);
+	*/
 }
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/gemini_pci.c linux/arch/ppc/kernel/gemini_pci.c
--- v2.4.0/linux/arch/ppc/kernel/gemini_pci.c	Tue May  2 13:05:39 2000
+++ linux/arch/ppc/kernel/gemini_pci.c	Wed Dec 31 16:00:00 1969
@@ -1,103 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/malloc.h>
-
-#include <asm/machdep.h>
-#include <asm/gemini.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include "pci.h"
-
-#define pci_config_addr(bus,dev,offset) \
-        (0x80000000 | (bus<<16) | (dev<<8) | offset)
-
-
-int
-gemini_pcibios_read_config_byte(unsigned char bus, unsigned char dev,
-                                unsigned char offset, unsigned char *val)
-{
-	unsigned long reg;
-	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
-	*val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_read_config_word(unsigned char bus, unsigned char dev,
-                                unsigned char offset, unsigned short *val)
-{
-	unsigned long reg;
-	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
-	*val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_read_config_dword(unsigned char bus, unsigned char dev,
-                                 unsigned char offset, unsigned int *val)
-{
-	*val = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_byte(unsigned char bus, unsigned char dev,
-                                 unsigned char offset, unsigned char val)
-{
-	unsigned long reg;
-	int shifts = offset & 0x3;
-
-	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
-	reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
-	grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), reg );
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_word(unsigned char bus, unsigned char dev,
-                                 unsigned char offset, unsigned short val)
-{
-	unsigned long reg;
-	int shifts = offset & 0x3;
-
-	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
-	reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
-	grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), reg );
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_dword(unsigned char bus, unsigned char dev,
-                                  unsigned char offset, unsigned int val)
-{
-	grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), val );
-	return PCIBIOS_SUCCESSFUL;
-}
-
-void __init gemini_pcibios_fixup(void)
-{
-	int i;
-	struct pci_dev *dev;
-	
-	pci_for_each_dev(dev) {
-		for(i = 0; i < 6; i++) {
-			if (dev->resource[i].flags & IORESOURCE_IO) {
-				dev->resource[i].start |= (0xfe << 24);
-				dev->resource[i].end |= (0xfe << 24);
-			}
-		}
-	}
-}
-
-decl_config_access_method(gemini);
-
-/* The "bootloader" for Synergy boards does none of this for us, so we need to
-   lay it all out ourselves... --Dan */
-void __init gemini_setup_pci_ptrs(void)
-{
-	set_config_access_method(gemini);
-	ppc_md.pcibios_fixup = gemini_pcibios_fixup;
-}
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/gemini_prom.S linux/arch/ppc/kernel/gemini_prom.S
--- v2.4.0/linux/arch/ppc/kernel/gemini_prom.S	Mon Apr 24 13:39:36 2000
+++ linux/arch/ppc/kernel/gemini_prom.S	Wed Dec 31 16:00:00 1969
@@ -1,96 +0,0 @@
-/*
- *  arch/ppc/kernel/gemini_prom.S
- *
- *  Not really prom support code (yet), but sort of anti-prom code.  The current
- *  bootloader does a number of things it shouldn't and doesn't do things that it
- *  should.  The stuff in here is mainly a hodge-podge collection of setup code
- *  to get the board up and running.
- *    ---Dan
- */
-
-#include "ppc_asm.tmpl"
-#include "ppc_defs.h"
-#include <linux/config.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/gemini.h>
-
-#define HID0_ABE (1<<3)
-
-/*
- *  On 750's the MMU is on when Linux is booted, so we need to clear out the
- *  bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
- *  and turn off the MMU.
- *
- */
-
-_GLOBAL(prom_init)
-_GLOBAL(gemini_prom_init)
-#ifdef CONFIG_SMP
-	/* Since the MMU's on, get stuff in rom space that we'll need */
-	lis	r4,GEMINI_CPUSTAT@h
-	ori	r4,r4,GEMINI_CPUSTAT@l
-	lbz	r5,0(r4)
-	andi.	r5,r5,3
-	mr	r24,r5		/* cpu # used later on */
-#endif
-	mfmsr	r4
-	li	r3,MSR_PR	/* ensure supervisor! */
-	ori	r3,r3,MSR_IR|MSR_DR
-	andc	r4,r4,r3
-	mtmsr	r4
-#if 0
-	/* zero out the bats now that the MMU is off */
-prom_no_mmu:	
-	li	r3,0
-        mtspr   IBAT0U,r3
-        mtspr   IBAT0L,r3
-        mtspr   IBAT1U,r3
-        mtspr   IBAT1L,r3
-        mtspr   IBAT2U,r3
-        mtspr   IBAT2L,r3
-        mtspr   IBAT3U,r3
-        mtspr   IBAT3L,r3
-
-        mtspr   DBAT0U,r3
-        mtspr   DBAT0L,r3
-        mtspr   DBAT1U,r3
-        mtspr   DBAT1L,r3
-        mtspr   DBAT2U,r3
-	mtspr   DBAT2L,r3
-        mtspr   DBAT3U,r3
-        mtspr   DBAT3L,r3
-#endif
-
-	/* the bootloader (as far as I'm currently aware) doesn't mess with page
-	   tables, but since we're already here, might as well zap these, too */
-	li	r4,0
-	mtspr	SDR1,r4
-
-	li	r4,16
-	mtctr	r4
-	li	r3,0
-	li	r4,0
-3:	mtsrin	r3,r4
-	addi	r3,r3,1
-	bdnz	3b
-
-#ifdef CONFIG_SMP
-	/* The 750 book (and Mot/IBM support) says that this will "assist" snooping
-	   when in SMP.  Not sure yet whether this should stay or leave... */
-	mfspr	r4,HID0
-	ori	r4,r4,HID0_ABE
-	mtspr	HID0,r4
-	sync
-#endif /* CONFIG_SMP */
-	blr
-
-/*  apparently, SMon doesn't pay attention to HID0[SRST].  Disable the MMU and
-    branch to 0xfff00100 */
-_GLOBAL(_gemini_reboot)
-	lis	r5,GEMINI_BOOT_INIT@h
-	ori	r5,r5,GEMINI_BOOT_INIT@l
-	li	r6,MSR_IP
-	mtspr	SRR0,r5
-	mtspr	SRR1,r6
-	rfi
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c
--- v2.4.0/linux/arch/ppc/kernel/gemini_setup.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/kernel/gemini_setup.c	Wed Dec 31 16:00:00 1969
@@ -1,562 +0,0 @@
-/*
- *  linux/arch/ppc/kernel/setup.c
- *
- *  Copyright (C) 1995 Linus Torvalds
- *  Adapted from 'alpha' version by Gary Thomas
- *  Modified by Cort Dougan (cort@cs.nmt.edu)
- *  Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
- *
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h> 
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/time.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/blk.h>
-#include <linux/console.h>
-#include <linux/openpic.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/m48t35.h>
-#include <asm/gemini.h>
-
-#include <asm/time.h>
-#include "local_irq.h"
-#include "open_pic.h"
-
-void gemini_setup_pci_ptrs(void);
-static int gemini_get_clock_speed(void);
-extern void gemini_pcibios_fixup(void);
-
-static char *gemini_board_families[] = {
-  "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
-};
-static int gemini_board_count = sizeof(gemini_board_families) /
-                                 sizeof(gemini_board_families[0]);
-
-static unsigned int cpu_7xx[16] = {
-	0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
-};
-static unsigned int cpu_6xx[16] = {
-	0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
-};
-
-int chrp_get_irq(struct pt_regs *);
-void chrp_post_irq(struct pt_regs* regs, int);
-
-static inline unsigned long _get_HID1(void)
-{
-	unsigned long val;
-
-	__asm__ __volatile__("mfspr %0,1009" : "=r" (val));
-	return val;
-}
-
-int
-gemini_get_cpuinfo(char *buffer)
-{
-	int len;
-	unsigned char reg, rev;
-	char *family;
-	unsigned int type;
-
-	reg = readb(GEMINI_FEAT);
-	family = gemini_board_families[((reg>>4) & 0xf)];
-	if (((reg>>4) & 0xf) > gemini_board_count)
-		printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
-
-	reg = readb(GEMINI_BREV);
-	type = (reg>>4) & 0xf;
-	rev = reg & 0xf;
-
-	reg = readb(GEMINI_BECO);
-
-	len = sprintf( buffer, "machine\t\t: Gemini %s%d, rev %c, eco %d\n", 
-		       family, type, (rev + 'A'), (reg & 0xf));
-
-	len = sprintf(buffer, "board\t\t: Gemini %s", family);
-	if (type > 9)
-		len += sprintf(buffer+len, "%c", (type - 10) + 'A');
-	else
-		len += sprintf(buffer+len, "%d", type);
-
-	len += sprintf(buffer+len, ", rev %c, eco %d\n",
-		       (rev + 'A'), (reg & 0xf));
-
-	len += sprintf(buffer+len, "clock\t\t: %dMhz\n", 
-		       gemini_get_clock_speed());
-
-	return len;
-}
-
-static u_char gemini_openpic_initsenses[] = {
-	1,
-	1,
-	1,
-	1,
-	0,
-	0,
-	1, /* remainder are level-triggered */
-};
-
-#define GEMINI_MPIC_ADDR (0xfcfc0000)
-#define GEMINI_MPIC_PCI_CFG (0x80005800)
-
-void __init gemini_openpic_init(void)
-{
-
-	OpenPIC = (volatile struct OpenPIC *)
-		grackle_read(0x80005800 + 0x10);
-#if 0	
-	grackle_write(GEMINI_MPIC_PCI_CFG + PCI_BASE_ADDRESS_0, 
-		      GEMINI_MPIC_ADDR);
-	grackle_write(GEMINI_MPIC_PCI_CFG + PCI_COMMAND, PCI_COMMAND_MEMORY);
-
-	OpenPIC = (volatile struct OpenPIC *) GEMINI_MPIC_ADDR;
-#endif
-	OpenPIC_InitSenses = gemini_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
-
-	ioremap( GEMINI_MPIC_ADDR, sizeof( struct OpenPIC ));
-}
-
-
-extern unsigned long loops_per_sec;
-extern int root_mountflags;
-extern char cmd_line[];
-
-void
-gemini_heartbeat(void)
-{
-	static unsigned long led = GEMINI_LEDBASE+(4*8);
-	static char direction = 8;
-	*(char *)led = 0;
-	if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
-	     (led + direction) < (GEMINI_LEDBASE+(4*8)) )
-		direction *= -1;
-	led += direction;
-	*(char *)led = 0xff;
-	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
-}
-
-void __init gemini_setup_arch(void)
-{
-	extern char cmd_line[];
-
-
-	loops_per_sec = 50000000;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* bootable off CDROM */
-	if (initrd_start)
-		ROOT_DEV = MKDEV(SCSI_CDROM_MAJOR, 0);
-	else
-#endif
-		ROOT_DEV = to_kdev_t(0x0801);
-
-	/* nothing but serial consoles... */  
-	sprintf(cmd_line, "%s console=ttyS0", cmd_line);
-
-	printk("Boot arguments: %s\n", cmd_line);
-
-	ppc_md.heartbeat = gemini_heartbeat;
-	ppc_md.heartbeat_reset = HZ/8;
-	ppc_md.heartbeat_count = 1;
-	
-	/* take special pains to map the MPIC, since it isn't mapped yet */
-	gemini_openpic_init();
-	/* start the L2 */
-	gemini_init_l2();
-}
-
-
-int
-gemini_get_clock_speed(void)
-{
-	unsigned long hid1, pvr = _get_PVR();
-	int clock;
-
-	hid1 = (_get_HID1() >> 28) & 0xf;
-	if (PVR_VER(pvr) == 8 ||
-	    PVR_VER(pvr) == 12)
-		hid1 = cpu_7xx[hid1];
-	else
-		hid1 = cpu_6xx[hid1];
-
-	switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
-
-	case 0:
-	default:
-		clock = (hid1*100)/3;
-		break;
-  
-	case 1:
-		clock = (hid1*125)/3;
-		break;
-  
-	case 2:
-		clock = (hid1*50);
-		break;
-	}
-
-	return clock;
-}
-
-#define L2CR_PIPE_LATEWR   (0x01800000)   /* late-write SRAM */
-#define L2CR_L2CTL         (0x00100000)   /* RAM control */
-#define L2CR_INST_DISABLE  (0x00400000)   /* disable for insn's */
-#define L2CR_L2I           (0x00200000)   /* global invalidate */
-#define L2CR_L2E           (0x80000000)   /* enable */
-#define L2CR_L2WT          (0x00080000)   /* write-through */
-
-void __init gemini_init_l2(void)
-{
-        unsigned char reg, brev, fam, creg;
-        unsigned long cache;
-        unsigned long pvr = _get_PVR();
-
-        reg = readb(GEMINI_L2CFG);
-        brev = readb(GEMINI_BREV);
-        fam = readb(GEMINI_FEAT);
-
-        switch(PVR_VER(pvr)) {
-
-        case 8:
-                if (reg & 0xc0)
-                        cache = (((reg >> 6) & 0x3) << 28);
-                else
-                        cache = 0x3 << 28;
-
-#ifdef CONFIG_SMP
-                /* Pre-3.0 processor revs had snooping errata.  Leave
-                   their L2's disabled with SMP. -- Dan */
-                if (PVR_CFG(pvr) < 3) {
-                        printk("Pre-3.0 750; L2 left disabled!\n");
-                        return;
-                }
-#endif /* CONFIG_SMP */
-
-                /* Special case: VGM5-B's came before L2 ratios were set on
-                   the board.  Processor speed shouldn't be too high, so
-                   set L2 ratio to 1:1.5.  */
-                if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
-                        reg |= 1;
-
-                /* determine best cache ratio based upon what the board
-                   tells us (which sometimes _may_ not be true) and
-                   the processor speed. */
-                else {
-                        if (gemini_get_clock_speed() > 250)
-                                reg = 2;
-                }
-                break;
-        case 12:
-	{
-		static unsigned long l2_size_val = 0;
-		
-		if (!l2_size_val)
-			l2_size_val = _get_L2CR();
-		cache = l2_size_val;
-                break;
-	}
-        case 4:
-        case 9:
-                creg = readb(GEMINI_CPUSTAT);
-                if (((creg & 0xc) >> 2) != 1)
-                        printk("Dual-604 boards don't support the use of L2\n");
-                else
-                        writeb(1, GEMINI_L2CFG);
-                return;
-        default:
-                printk("Unknown processor; L2 left disabled\n");
-                return;
-        }
-
-        cache |= ((1<<reg) << 25);
-        cache |= (L2CR_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE);
-        _set_L2CR(0);
-        _set_L2CR(cache | L2CR_L2I | L2CR_L2E);
-
-}
-
-void
-gemini_restart(char *cmd)
-{
-	__cli();
-	/* make a clean restart, not via the MPIC */
-	_gemini_reboot();
-	for(;;);
-}
-
-void
-gemini_power_off(void)
-{
-	for(;;);
-}
-
-void
-gemini_halt(void)
-{
-	gemini_restart(NULL);
-}
-
-void __init gemini_init_IRQ(void)
-{
-	int i;
-
-	/* gemini has no 8259 */
-	open_pic_irq_offset = 0;
-	for( i=0; i < NR_IRQS; i++ ) 
-		irq_desc[i].handler = &open_pic;
-	openpic_init(1);
-#ifdef CONFIG_SMP
- 	request_irq(OPENPIC_VEC_IPI, openpic_ipi_action,
- 		    0, "IPI0", 0);
- 	request_irq(OPENPIC_VEC_IPI+1, openpic_ipi_action,
- 		    0, "IPI1 (invalidate TLB)", 0);
- 	request_irq(OPENPIC_VEC_IPI+2, openpic_ipi_action,
- 		    0, "IPI2 (stop CPU)", 0);
- 	request_irq(OPENPIC_VEC_IPI+3, openpic_ipi_action,
- 		    0, "IPI3 (reschedule)", 0);
-#endif	/* CONFIG_SMP */
-}
-
-#define gemini_rtc_read(x)       (readb(GEMINI_RTC+(x)))
-#define gemini_rtc_write(val,x)  (writeb((val),(GEMINI_RTC+(x))))
-
-/* ensure that the RTC is up and running */
-long __init gemini_time_init(void)
-{
-	unsigned char reg;
-
-	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
-
-	if ( reg & M48T35_RTC_STOPPED ) {
-		printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
-		gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
-		gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
-	}
-	return 0;
-}
-
-#undef DEBUG_RTC
-
-unsigned long
-gemini_get_rtc_time(void)
-{
-	unsigned int year, mon, day, hour, min, sec;
-	unsigned char reg;
-
-	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
-	gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
-#ifdef DEBUG_RTC
-	printk("get rtc: reg = %x\n", reg);
-#endif
-  
-	do {
-		sec = gemini_rtc_read(M48T35_RTC_SECONDS);
-		min = gemini_rtc_read(M48T35_RTC_MINUTES);
-		hour = gemini_rtc_read(M48T35_RTC_HOURS);
-		day = gemini_rtc_read(M48T35_RTC_DOM);
-		mon = gemini_rtc_read(M48T35_RTC_MONTH);
-		year = gemini_rtc_read(M48T35_RTC_YEAR);
-	} while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
-#ifdef DEBUG_RTC
-	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
-	       sec, min, hour, day, mon, year);
-#endif
-
-	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
-
-	BCD_TO_BIN(sec);
-	BCD_TO_BIN(min);
-	BCD_TO_BIN(hour);
-	BCD_TO_BIN(day);
-	BCD_TO_BIN(mon);
-	BCD_TO_BIN(year);
-
-	if ((year += 1900) < 1970)
-		year += 100;
-#ifdef DEBUG_RTC
-	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
-	       sec, min, hour, day, mon, year);
-#endif
-
-	return mktime( year, mon, day, hour, min, sec );
-}
-
-
-int
-gemini_set_rtc_time( unsigned long now )
-{
-	unsigned char reg;
-	struct rtc_time tm;
-
-	to_tm( now, &tm );
-
-	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
-#if DEBUG_RTC
-	printk("set rtc: reg = %x\n", reg);
-#endif
-  
-	gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
-#if DEBUG_RTC
-	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
-	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
-#endif
-  
-	tm.tm_year -= 1900;
-	BIN_TO_BCD(tm.tm_sec);
-	BIN_TO_BCD(tm.tm_min);
-	BIN_TO_BCD(tm.tm_hour);
-	BIN_TO_BCD(tm.tm_mon);
-	BIN_TO_BCD(tm.tm_mday);
-	BIN_TO_BCD(tm.tm_year);
-#ifdef DEBUG_RTC
-	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
-	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
-#endif
-
-	gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
-	gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
-	gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
-	gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
-	gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
-	gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
-
-	/* done writing */
-	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
-
-	if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
-		time_state = TIME_OK;
-  
-	return 0;
-}
-
-/*  use the RTC to determine the decrementer count */
-void __init gemini_calibrate_decr(void)
-{
-	int freq, divisor;
-	unsigned char reg;
-
-	/* determine processor bus speed */
-	reg = readb(GEMINI_BSTAT);
-
-	switch(((reg & 0x0c)>>2)&0x3) {
-	case 0:
-	default:
-		freq = 66;
-		break;
-	case 1:
-		freq = 83;
-		break;
-	case 2:
-		freq = 100;
-		break;
-	}
-
-	freq *= 1000000;
-	divisor = 4;
-	decrementer_count = freq / HZ / divisor;
-	count_period_num = divisor;
-	count_period_den = freq / 1000000;
-}
-
-int gemini_get_irq( struct pt_regs *regs )
-{
-        int irq;
-
-        irq = openpic_irq( smp_processor_id() );
-        if (irq == OPENPIC_VEC_SPURIOUS)
-                /*
-                 * Spurious interrupts should never be
-                 * acknowledged
-                 */
-		irq = -1;
-	/*
-	 * I would like to openpic_eoi here but there seem to be timing problems
-	 * between the openpic ack and the openpic eoi.
-	 *   -- Cort
-	 */
-	return irq;
-}
-
-void gemini_post_irq(struct pt_regs* regs, int irq)
-{
-	/*
-	 * If it's an i8259 irq then we've already done the
-	 * openpic irq.  So we just check to make sure the controller
-	 * is an openpic and if it is then eoi
-	 *
-	 * We do it this way since our irq_desc[irq].handler can change
-	 * with RTL and no longer be open_pic -- Cort
-	 */
-	if ( irq >= open_pic_irq_offset)
-		openpic_eoi( smp_processor_id() );
-}
-
-
-void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
-			unsigned long r6, unsigned long r7)
-{
-	int i;
-	int chrp_get_irq( struct pt_regs * );
-
-	for(i = 0; i < GEMINI_LEDS; i++)
-		gemini_led_off(i);
- 
-	gemini_setup_pci_ptrs();
-
-	ISA_DMA_THRESHOLD = 0;
-	DMA_MODE_READ = 0;
-	DMA_MODE_WRITE = 0;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if ( r4 )
-	{
-		initrd_start = r4 + KERNELBASE;
-		initrd_end = r5 + KERNELBASE;
-	}
-#endif
-
-	ppc_md.setup_arch = gemini_setup_arch;
-	ppc_md.setup_residual = NULL;
-	ppc_md.get_cpuinfo = gemini_get_cpuinfo;
-	ppc_md.irq_cannonicalize = NULL;
-	ppc_md.init_IRQ = gemini_init_IRQ;
-	ppc_md.get_irq = gemini_get_irq;
-	ppc_md.post_irq = gemini_post_irq;
-	ppc_md.init = NULL;
-
-	ppc_md.restart = gemini_restart;
-	ppc_md.power_off = gemini_power_off;
-	ppc_md.halt = gemini_halt;
-
-	ppc_md.time_init = gemini_time_init;
-	ppc_md.set_rtc_time = gemini_set_rtc_time;
-	ppc_md.get_rtc_time = gemini_get_rtc_time;
-	ppc_md.calibrate_decr = gemini_calibrate_decr;
-
-	/* no keyboard/mouse/video stuff yet.. */
-	ppc_md.kbd_setkeycode = NULL;
-	ppc_md.kbd_getkeycode = NULL;
-	ppc_md.kbd_translate = NULL;
-	ppc_md.kbd_unexpected_up = NULL;
-	ppc_md.kbd_leds = NULL;
-	ppc_md.kbd_init_hw = NULL;
-#ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.ppc_kbd_sysrq_xlate = NULL;
-#endif
-	ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
-}
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/hashtable.S linux/arch/ppc/kernel/hashtable.S
--- v2.4.0/linux/arch/ppc/kernel/hashtable.S	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/kernel/hashtable.S	Mon Jan 22 15:41:15 2001
@@ -56,7 +56,6 @@
 #ifdef CONFIG_PPC64BRIDGE
 	mfmsr	r0
 	clrldi	r0,r0,1		/* make sure it's in 32-bit mode */
-	sync
 	MTMSRD(r0)
 	isync
 #endif
@@ -112,23 +111,31 @@
 #endif
 	tophys(r2,r5)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r6,0(r2)		/* get linux-style pte */
 	ori	r4,r4,1			/* set _PAGE_PRESENT bit in access */
+	rlwinm	r5,r4,5,24,24		/* _PAGE_RW access -> _PAGE_DIRTY */
+	rlwimi	r5,r4,7,22,22		/* _PAGE_RW -> _PAGE_HWWRITE */
+	ori	r5,r5,0x100		/* set _PAGE_ACCESSED */
+retry:
+	lwz	r6,0(r2)		/* get linux-style pte */
 	andc.	r0,r4,r6		/* check access & ~permission */
 #ifdef CONFIG_SMP
 	bne-	hash_page_out		/* return if access not permitted */
 #else
 	bnelr-
 #endif
+	andc.	r0,r5,r6		/* any bits not yet set? */
+	beq	2f
 
-	ori	r6,r6,0x100		/* set _PAGE_ACCESSED in pte */
-	rlwinm	r5,r4,5,24,24		/* _PAGE_RW access -> _PAGE_DIRTY */
-	rlwimi	r5,r4,7,22,22		/* _PAGE_RW -> _PAGE_HWWRITE */
-	or	r6,r6,r5
-	stw	r6,0(r2)		/* update PTE (accessed/dirty bits) */
+	/* Update the linux PTE atomically */
+	lwarx	r0,0,r2			/* refetch the pte and check */
+	cmpw	0,r0,r6			/* that it hasn't been changed */
+	bne-	retry			/* retry if it has */
+	or	r6,r6,r5		/* set accessed/dirty bits */
+	stwcx.	r6,0,r2			/* attempt to update PTE */
+	bne-	retry			/* retry if someone got there first */
 
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	rlwinm	r4,r6,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
+2:	rlwinm	r4,r6,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
 	rlwimi	r6,r6,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
 	ori	r4,r4,0xe04		/* clear out reserved bits */
 	andc	r6,r6,r4		/* PP=2 or 0, when _PAGE_HWWRITE */
@@ -166,12 +173,16 @@
 	rlwimi	r4,r5,32-5,25-Hash_bits,24	/* (VSID & hash_mask) << 7 */
 	rlwinm	r0,r3,32-5,25-Hash_bits,24	/* (PI & hash_mask) << 7 */
 	xor	r4,r4,r0		/* make primary hash */
+	li	r2,8			/* PTEs/group */
 
+#ifndef CONFIG_SMP
+	/* We don't do this for SMP - another cpu could have put in
+	   the appropriate PTE since we took the exception.  -- paulus. */
 	/* See whether it was a PTE not found exception or a
 	   protection violation. */
 	andis.	r0,r20,0x4000
-	li	r2,8			/* PTEs/group */
 	bne	10f			/* no PTE: go look for an empty slot */
+#endif /* CONFIG_SMP */
 	tlbie	r3			/* invalidate TLB entry */
 
 	/* Search the primary PTEG for a PTE whose 1st dword matches r5 */
@@ -263,7 +274,6 @@
 	std	r5,0(r3)
 found_slot:
 	std	r6,8(r3)
-	sync
 
 #else /* CONFIG_SMP */
 /*
@@ -311,12 +321,16 @@
 	rlwimi	r4,r5,32-1,26-Hash_bits,25	/* (VSID & hash_mask) << 6 */
 	rlwinm	r0,r3,32-6,26-Hash_bits,25	/* (PI & hash_mask) << 6 */
 	xor	r4,r4,r0		/* make primary hash */
+	li	r2,8			/* PTEs/group */
 
+#ifndef CONFIG_SMP
+	/* We don't do this for SMP - another cpu could have put in
+	   the appropriate PTE since we took the exception.  -- paulus. */
 	/* See whether it was a PTE not found exception or a
 	   protection violation. */
 	andis.	r0,r20,0x4000
-	li	r2,8			/* PTEs/group */
 	bne	10f			/* no PTE: go look for an empty slot */
+#endif /* CONFIG_SMP */
 	tlbie	r3			/* invalidate TLB entry */
 
 	/* Search the primary PTEG for a PTE whose 1st word matches r5 */
@@ -394,7 +408,6 @@
 	stw	r5,0(r3)
 found_slot:
 	stw	r6,4(r3)
-	sync
 
 #else /* CONFIG_SMP */
 /*
@@ -428,6 +441,8 @@
 #endif /* CONFIG_SMP */
 #endif /* CONFIG_PPC64BRIDGE */
 
+	sync		/* make sure pte updates get to memory */
+
 /*
  * Update the hash table miss count.  We only want misses here
  * that _are_ valid addresses and have a pte otherwise we don't
@@ -517,7 +532,7 @@
 	   a hash table miss while we have the hash table locked,
 	   or we'll get a deadlock.  -paulus */
 	mfmsr	r10
-	sync
+	SYNC
 	rlwinm	r0,r10,0,17,15	/* clear bit 16 (MSR_EE) */
 	mtmsr	r0
 	SYNC
@@ -616,7 +631,7 @@
 	   a hash table miss while we have the hash table locked,
 	   or we'll get a deadlock.  -paulus */
 	mfmsr	r10
-	sync
+	SYNC
 	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
 	mtmsr	r0
 	SYNC
@@ -628,10 +643,14 @@
 	oris	r8,r8,9
 10:	lwarx	r7,0,r9
 	cmpi	0,r7,0
-	bne-	10b
+	bne-	11f
 	stwcx.	r8,0,r9
-	bne-	10b
-	eieio
+	beq+	12f
+11:	lwz	r7,0(r9)
+	cmpi	0,r7,0
+	beq	10b
+	b	11b
+12:	eieio
 #endif
 #ifndef CONFIG_PPC64BRIDGE
 	rlwinm	r3,r3,11,1,20		/* put context into vsid */
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.4.0/linux/arch/ppc/kernel/head.S	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/kernel/head.S	Mon Jan 22 15:41:15 2001
@@ -149,6 +149,8 @@
 	mr	r28,r6
 	mr	r27,r7
 	li	r24,0			/* cpu # */
+	/* N.B. prom_init clears the BSS even if it doesn't do
+	 * anything else -- paulus. */
 	bl	prom_init
 
 #ifdef CONFIG_APUS
@@ -159,7 +161,6 @@
 	bl	fix_mem_constants
 #endif /* CONFIG_APUS */
 
-#ifndef CONFIG_GEMINI
 /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
  * the physical address we are running at, returned by prom_init()
  */
@@ -167,7 +168,6 @@
 __after_mmu_off:
 	bl	clear_bats
 	bl	flush_tlbs
-#endif
 
 #ifndef CONFIG_POWER4
 	/* POWER4 doesn't have BATs */
@@ -290,6 +290,7 @@
 	addi	r3,r1,STACK_FRAME_OVERHEAD;	\
 	li	r20,MSR_KERNEL;			\
 	bl	transfer_to_handler; 		\
+i##n:						\
 	.long	hdlr;				\
 	.long	ret_from_except
 
@@ -301,17 +302,13 @@
 	addi	r3,r1,STACK_FRAME_OVERHEAD;	\
 	li	r20,MSR_KERNEL;			\
 	bl	transfer_to_handler; 		\
+i##n:						\
 	.long	hdlr;				\
 	.long	ret_from_except
 
 /* System reset */
-#ifdef CONFIG_SMP /* MVME/MTX and gemini start the secondary here */
-#ifdef CONFIG_GEMINI
-	. = 0x100
-	b	__secondary_start_gemini
-#else /* CONFIG_GEMINI */
+#ifdef CONFIG_SMP /* MVME/MTX start the secondary here */
 	STD_EXCEPTION(0x100, Reset, __secondary_start_psurge)
-#endif /* CONFIG_GEMINI */
 #else
 	STD_EXCEPTION(0x100, Reset, UnknownException)
 #endif
@@ -344,6 +341,7 @@
 	li	r20,MSR_KERNEL
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
 	bl	transfer_to_handler
+i0x300:
 	.long	do_page_fault
 	.long	ret_from_except
 
@@ -384,6 +382,7 @@
 	li	r20,MSR_KERNEL
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
 	bl	transfer_to_handler
+i0x400:
 	.long	do_page_fault
 	.long	ret_from_except
 
@@ -429,6 +428,7 @@
 	li	r20,MSR_KERNEL
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
 	bl	transfer_to_handler
+i0x600:
 	.long	AlignmentException
 	.long	ret_from_except
 
@@ -441,6 +441,7 @@
 	li	r20,MSR_KERNEL
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
 	bl	transfer_to_handler
+i0x700:
 	.long	ProgramCheckException
 	.long	ret_from_except
 
@@ -452,6 +453,7 @@
 	bne	load_up_fpu		/* if from user, just load it up */
 	li	r20,MSR_KERNEL
 	bl	transfer_to_handler	/* if from kernel, take a trap */
+i0x800:
 	.long	KernelFP
 	.long	ret_from_except
 
@@ -575,7 +577,7 @@
 	mfmsr	r0		/* Restore "normal" registers */
 	xoris	r0,r0,MSR_TGPR>>16
 	mtcrf	0x80,r3		/* Restore CR0 */
-	sync			/* Some chip revs have problems here... */
+	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0
 	b	InstructionAccess
 
@@ -646,7 +648,7 @@
 	mfmsr	r0		/* Restore "normal" registers */
 	xoris	r0,r0,MSR_TGPR>>16
 	mtcrf	0x80,r3		/* Restore CR0 */
-	sync			/* Some chip revs have problems here... */
+	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0
 	b	DataAccess
 	
@@ -843,7 +845,7 @@
 #endif /* CONFIG_PPC64BRIDGE */
 	SYNC
 	MTMSRD(r5)			/* enable use of fpu now */
-	SYNC
+	isync
 /*
  * For SMP, we don't do lazy FPU switching because it just gets too
  * horrendously complex, especially when a task switches from one CPU
@@ -929,7 +931,7 @@
 	oris	r5,r5,MSR_VEC@h
 	SYNC
 	mtmsr	r5			/* enable use of AltiVec now */
-	SYNC
+	isync
 /*
  * For SMP, we don't do lazy AltiVec switching because it just gets too
  * horrendously complex, especially when a task switches from one CPU
@@ -1023,7 +1025,7 @@
 	oris	r5,r5,MSR_VEC@h
 	SYNC
 	mtmsr	r5			/* enable use of AltiVec now */
-	SYNC
+	isync
 	cmpi	0,r3,0
 	beqlr-				/* if no previous owner, done */
 	addi	r3,r3,THREAD		/* want THREAD of task */
@@ -1064,7 +1066,7 @@
 	ori	r5,r5,MSR_FP
 	SYNC
 	mtmsr	r5			/* enable use of fpu now */
-	SYNC
+	isync
 	cmpi	0,r3,0
 	beqlr-				/* if no previous owner, done */
 	addi	r3,r3,THREAD	        /* want THREAD of task */
@@ -1163,6 +1165,7 @@
 	icbi	r0,r14			 /* flush the icache line */
 	cmpw	r12,r13
 	bne     1b
+	isync
 
 /*
  * Map the memory where the exception handlers will
@@ -1208,9 +1211,9 @@
 	
 	mfmsr	20
 	xori	r20,r20,MSR_DR
-	sync
+	SYNC
 	mtmsr	r20
-	sync
+	isync
 
 	lis	r4,APUS_IPL_EMU@h
 
@@ -1243,9 +1246,9 @@
 	
 	mfmsr	r20
 	xori	r20,r20,MSR_DR
-	sync
+	SYNC
 	mtmsr	r20
-	sync
+	isync
 
 	stw	r3,(_CCR+4)(r21);
 
@@ -1263,28 +1266,24 @@
 #endif /* CONFIG_APUS */
 
 #ifdef CONFIG_SMP
-#ifdef CONFIG_GEMINI
-	.globl	__secondary_start_gemini
-__secondary_start_gemini:
-        mfspr   r4,HID0
-        ori     r4,r4,HID0_ICFI
-        li      r3,0
-        ori     r3,r3,HID0_ICE
-        andc    r4,r4,r3
-        mtspr   HID0,r4
-        sync
-        bl      prom_init
-        b       __secondary_start
-#endif /* CONFIG_GEMINI */
-	
 	.globl	__secondary_start_psurge
 __secondary_start_psurge:
 	li	r24,1			/* cpu # */
+	b	__secondary_start_psurge99
+	.globl	__secondary_start_psurge2
+__secondary_start_psurge2:
+	li	r24,2			/* cpu # */
+	b	__secondary_start_psurge99
+	.globl	__secondary_start_psurge3
+__secondary_start_psurge3:
+	li	r24,3			/* cpu # */
+	b	__secondary_start_psurge99
+__secondary_start_psurge99:
 	/* we come in here with IR=0 and DR=1, and DBAT 0
 	   set to map the 0xf0000000 - 0xffffffff region */
 	mfmsr	r0
 	rlwinm	r0,r0,0,28,26		/* clear DR (0x10) */
-	sync
+	SYNC
 	mtmsr	r0
 	isync
 
@@ -1293,7 +1292,7 @@
 #ifdef CONFIG_PPC64BRIDGE
 	mfmsr	r0
 	clrldi	r0,r0,1		/* make sure it's in 32-bit mode */
-	sync
+	SYNC
 	MTMSRD(r0)
 	isync
 #else
@@ -1445,21 +1444,6 @@
 	li	r3,0
 	mtspr	SPRG2,r3	/* 0 => r1 has kernel sp */
 
-	/* Clear out the BSS */
-	lis	r11,_end@ha
-	addi	r11,r11,_end@l
-	lis	r8,__bss_start@ha
-	addi	r8,r8,__bss_start@l
-	subf	r11,r8,r11
-	addi	r11,r11,3
-	rlwinm.	r11,r11,30,2,31
-	beq	2f
-	addi	r8,r8,-4
-	mtctr	r11
-	li	r0,0
-3:	stwu	r0,4(r8)
-	bdnz	3b
-2:
 	/* stack */
 	addi	r1,r2,TASK_UNION_SIZE
 	li	r0,0
@@ -1504,7 +1488,7 @@
 	RFI
 /* Load up the kernel context */
 2:
-	SYNC			/* Force all PTE updates to finish */
+	sync			/* Force all PTE updates to finish */
 	tlbia			/* Clear all TLB entries */
 	sync			/* wait for tlbia/tlbie to finish */
 #ifdef CONFIG_SMP
@@ -1552,7 +1536,6 @@
  *  -- Cort 
  */
 clear_bats:
-#if !defined(CONFIG_GEMINI)
 	li	r20,0
 	mfspr	r9,PVR
 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
@@ -1576,10 +1559,8 @@
 	mtspr	IBAT2L,r20
 	mtspr	IBAT3U,r20
 	mtspr	IBAT3L,r20
-#endif /* !defined(CONFIG_GEMINI) */
 	blr
 
-#ifndef CONFIG_GEMINI
 flush_tlbs:
 	lis	r20, 0x40
 1:	addic.	r20, r20, -0x1000
@@ -1598,7 +1579,6 @@
 	mtspr	SRR1,r3
 	sync
 	RFI
-#endif
 
 #ifndef CONFIG_POWER4	
 /*
@@ -1745,3 +1725,12 @@
 	.globl	cmd_line
 cmd_line:
 	.space	512
+
+	.globl intercept_table
+intercept_table:
+	.long 0, i0x100, i0x200, i0x300, i0x400, 0, i0x600, i0x700
+	.long i0x800, 0, 0, 0, 0, i0xd00, 0, 0
+	.long 0, 0, 0, i0x1300, 0, 0, 0, 0
+	.long 0, 0, 0, 0, 0, 0, 0, 0
+	.long 0, 0, 0, 0, 0, 0, 0, 0
+	.long 0, 0, 0, 0, 0, 0, 0, 0
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/i8259.c linux/arch/ppc/kernel/i8259.c
--- v2.4.0/linux/arch/ppc/kernel/i8259.c	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/kernel/i8259.c	Mon Jan 22 15:41:15 2001
@@ -10,12 +10,15 @@
 #define cached_A1 (cached_8259[0])
 #define cached_21 (cached_8259[1])
 
+spinlock_t i8259_lock = SPIN_LOCK_UNLOCKED;
+
 int i8259_pic_irq_offset;
 
 int i8259_irq(int cpu)
 {
 	int irq;
 	
+	spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
         /*
          * Perform an interrupt acknowledge cycle on controller 1
          */                                                             
@@ -40,14 +43,20 @@
 		 * interrupt
 		 */
 		outb(0x0b, 0x20);
-		if(~inb(0x20)&0x80)
+		if(~inb(0x20)&0x80) {
+			spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
 			return -1;
+		}
 	}
+	spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
 	return irq;
 }
 
 static void i8259_mask_and_ack_irq(unsigned int irq_nr)
 {
+	unsigned long flags;
+	
+	spin_lock_irqsave(&i8259_lock, flags);
         if ( irq_nr >= i8259_pic_irq_offset )
                 irq_nr -= i8259_pic_irq_offset;
 
@@ -63,6 +72,7 @@
                 outb(cached_21,0x21);
                 outb(0x20,0x20);        /* Non-specific EOI */                 
         }                                                                
+	spin_unlock_irqrestore(&i8259_lock, flags);
 }
 
 static void i8259_set_irq_mask(int irq_nr)
@@ -73,6 +83,9 @@
 
 static void i8259_mask_irq(unsigned int irq_nr)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259_lock, flags);
         if ( irq_nr >= i8259_pic_irq_offset )
                 irq_nr -= i8259_pic_irq_offset;
         if ( irq_nr < 8 )
@@ -80,11 +93,14 @@
         else
                 cached_A1 |= 1 << (irq_nr-8);
         i8259_set_irq_mask(irq_nr);
+	spin_unlock_irqrestore(&i8259_lock, flags);
 }
 
 static void i8259_unmask_irq(unsigned int irq_nr)
 {
+	unsigned long flags;
 
+	spin_lock_irqsave(&i8259_lock, flags);
         if ( irq_nr >= i8259_pic_irq_offset )
                 irq_nr -= i8259_pic_irq_offset;
         if ( irq_nr < 8 )
@@ -92,6 +108,13 @@
         else
                 cached_A1 &= ~(1 << (irq_nr-8));
         i8259_set_irq_mask(irq_nr);
+	spin_unlock_irqrestore(&i8259_lock, flags);
+}
+
+static void i8259_end_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		i8259_unmask_irq(irq);
 }
 
 struct hw_interrupt_type i8259_pic = {
@@ -101,11 +124,15 @@
         i8259_unmask_irq,
         i8259_mask_irq,
         i8259_mask_and_ack_irq,
-        0
+        i8259_end_irq,
+        NULL
 };
 
 void __init i8259_init(void)
 {
+	unsigned long flags;
+	
+	spin_lock_irqsave(&i8259_lock, flags);
         /* init master interrupt controller */
         outb(0x11, 0x20); /* Start init sequence */
         outb(0x00, 0x21); /* Vector base */
@@ -120,7 +147,7 @@
         outb(0xFF, 0xA1); /* Mask all */
         outb(cached_A1, 0xA1);
         outb(cached_21, 0x21);
+	spin_unlock_irqrestore(&i8259_lock, flags);
         request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
                      "82c59 secondary cascade", NULL );
-        enable_irq(i8259_pic_irq_offset + 2);  /* Enable cascade interrupt */
 }
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.4.0/linux/arch/ppc/kernel/idle.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/kernel/idle.c	Mon Jan 22 15:41:15 2001
@@ -47,24 +47,35 @@
 
 int idled(void)
 {
+	int do_power_save = 0;
+
+	/* only sleep on the 603-family/750 processors */
+	switch (_get_PVR() >> 16) {
+	case 3:			/* 603 */
+	case 6:			/* 603e */
+	case 7:			/* 603ev */
+	case 8:			/* 750 */
+	case 12:		/* 7400 */
+		do_power_save = 1;
+	}
+
 	/* endless loop with no priority at all */
 	current->nice = 20;
 	current->counter = -100;
 	init_idle();	
 	for (;;)
 	{
-		__sti();
-		
-		check_pgt_cache();
-
-		/*if ( !current->need_resched && zero_paged_on ) zero_paged();*/
-		if ( !current->need_resched && htab_reclaim_on ) htab_reclaim();
-		if ( !current->need_resched ) power_save();
+		/*if ( !current->need_resched && zero_paged_on )
+			zero_paged();*/
+		if (!current->need_resched && htab_reclaim_on)
+			htab_reclaim();
+		if (do_power_save && !current->need_resched)
+			power_save();
 
-#ifdef CONFIG_SMP
-		if (current->need_resched)
-#endif
+		if (current->need_resched) {
 			schedule();
+			check_pgt_cache();
+		}
 	}
 	return 0;
 }
@@ -278,31 +289,31 @@
 
 void power_save(void)
 {
-	unsigned long msr, hid0;
-
-	/* only sleep on the 603-family/750 processors */
-	switch (_get_PVR() >> 16) {
-	case 3:			/* 603 */
-	case 6:			/* 603e */
-	case 7:			/* 603ev */
-	case 8:			/* 750 */
-	case 12:		/* 7400 */
-		save_flags(msr);
-		__cli();
-		if (!current->need_resched) {
-			asm("mfspr %0,1008" : "=r" (hid0) :);
-			hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE);
-			hid0 |= (powersave_nap? HID0_NAP: HID0_DOZE) | HID0_DPM;
-			asm("mtspr 1008,%0" : : "r" (hid0));
+	unsigned long hid0;
+	/*
+	 * Disable interrupts to prevent a lost wakeup
+	 * when going to sleep.  This is necessary even with
+	 * RTLinux since we are not guaranteed an interrupt
+	 * didn't come in and is waiting for a __sti() before
+	 * emulating one.  This way, we really do hard disable.
+	 * 
+	 * We assume that we're sti-ed when we come in here.  We
+	 * are in the idle loop so if we're cli-ed then it's a bug
+	 * anyway.
+	 *  -- Cort
+	 */
+	_nmask_and_or_msr(MSR_EE, 0);
+	if (!current->need_resched)
+	{
+		asm("mfspr %0,1008" : "=r" (hid0) :);
+		hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE);
+		hid0 |= (powersave_nap? HID0_NAP: HID0_DOZE) | HID0_DPM;
+		asm("mtspr 1008,%0" : : "r" (hid0));
 		
-			/* set the POW bit in the MSR, and enable interrupts
-			 * so we wake up sometime! */
-			__sti(); /* this keeps rtl from getting confused -- Cort */
-			_nmask_and_or_msr(0, MSR_POW | MSR_EE);
-		}
-		restore_flags(msr);
-	default:
-		return;
+		/* set the POW bit in the MSR, and enable interrupts
+		 * so we wake up sometime! */
+		_nmask_and_or_msr(0, MSR_POW | MSR_EE);
 	}
+	_nmask_and_or_msr(0, MSR_EE);
 }
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/indirect_pci.c linux/arch/ppc/kernel/indirect_pci.c
--- v2.4.0/linux/arch/ppc/kernel/indirect_pci.c	Thu Oct  7 10:17:08 1999
+++ linux/arch/ppc/kernel/indirect_pci.c	Mon Jan 22 15:41:15 2001
@@ -9,113 +9,59 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/kernel.h>
 #include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-unsigned int * pci_config_address;
-unsigned char * pci_config_data;
-
-int indirect_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-			     unsigned char offset, unsigned char *val)
-{
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	
-	out_be32(pci_config_address, 
-		 ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
-
-	*val= in_8(pci_config_data + (offset&3));
-
-	restore_flags(flags);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int indirect_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-			     unsigned char offset, unsigned short *val)
-{
-	unsigned long flags;
-	
-	if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	save_flags(flags); cli();
-	
-	out_be32(pci_config_address, 
-		 ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
-
-	*val= in_le16((unsigned short *)(pci_config_data + (offset&3)));
-
-	restore_flags(flags);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int indirect_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-			     unsigned char offset, unsigned int *val)
-{
-	unsigned long flags;
-	
-	if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	save_flags(flags); cli();
-	
-	out_be32(pci_config_address, 
-		 ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
-
-	*val= in_le32((unsigned *)pci_config_data);
-
-	restore_flags(flags);
-	return PCIBIOS_SUCCESSFUL;
-}
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
 
-int indirect_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-			     unsigned char offset, unsigned char val)
-{
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	
-	out_be32(pci_config_address, 
-		 ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
-
-	out_8(pci_config_data + (offset&3), val);
-
-	restore_flags(flags);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int indirect_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-			     unsigned char offset, unsigned short val)
-{
-	unsigned long flags;
-
-	if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	save_flags(flags); cli();
-	
-	out_be32(pci_config_address, 
-		 ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
-
-	out_le16((unsigned short *)(pci_config_data + (offset&3)), val);
-
-	restore_flags(flags);
-	return PCIBIOS_SUCCESSFUL;
+#include <asm/init.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "pci.h"
+
+#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
+
+#define INDIRECT_PCI_OP(rw, size, type, op, mask)			 \
+static int								 \
+indirect_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
+{									 \
+	struct pci_controller *hose = dev->sysdata;			 \
+									 \
+	out_be32(hose->cfg_addr, 					 \
+		 ((offset & 0xfc) << 24) | (dev->devfn << 16)		 \
+		 | (dev->bus->number << 8) | 0x80);			 \
+	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);	 \
+	return PCIBIOS_SUCCESSFUL;    					 \
+}
+
+INDIRECT_PCI_OP(read, byte, u8 *, in_8, 3)
+INDIRECT_PCI_OP(read, word, u16 *, in_le16, 2)
+INDIRECT_PCI_OP(read, dword, u32 *, in_le32, 0)
+INDIRECT_PCI_OP(write, byte, u8, out_8, 3)
+INDIRECT_PCI_OP(write, word, u16, out_le16, 2)
+INDIRECT_PCI_OP(write, dword, u32, out_le32, 0)
+
+static struct pci_ops indirect_pci_ops =
+{
+	indirect_read_config_byte,
+	indirect_read_config_word,
+	indirect_read_config_dword,
+	indirect_write_config_byte,
+	indirect_write_config_word,
+	indirect_write_config_dword
+};
+
+void __init
+setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+	hose->ops = &indirect_pci_ops;
+	hose->cfg_addr = (unsigned int *) ioremap(cfg_addr, 4);
+	hose->cfg_data = (unsigned char *) ioremap(cfg_data, 4);
 }
 
-int indirect_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-			     unsigned char offset, unsigned int val)
-{
-	unsigned long flags;
-
-	if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	save_flags(flags); cli();
-	
-	out_be32(pci_config_address, 
-		 ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
-
-	out_le32((unsigned *)pci_config_data, val);
-
-	restore_flags(flags);
-	return PCIBIOS_SUCCESSFUL;
-}
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.4.0/linux/arch/ppc/kernel/irq.c	Sat Nov 11 18:19:56 2000
+++ linux/arch/ppc/kernel/irq.c	Mon Jan 22 15:41:15 2001
@@ -41,11 +41,11 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/malloc.h>
-#include <linux/openpic.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -64,19 +64,22 @@
 
 #include "local_irq.h"
 
-extern volatile unsigned long ipi_count;
+atomic_t ipi_recv;
+atomic_t ipi_sent;
 void enable_irq(unsigned int irq_nr);
 void disable_irq(unsigned int irq_nr);
 
-volatile unsigned char *chrp_int_ack_special;
+static void register_irq_proc (unsigned int irq);
 
 #define MAXCOUNT 10000000
 
-irq_desc_t irq_desc[NR_IRQS];
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
+	{ [0 ... NR_IRQS-1] = { 0, NULL, NULL, 0, SPIN_LOCK_UNLOCKED}};
+	
 int ppc_spurious_interrupts = 0;
 struct irqaction *ppc_irq_action[NR_IRQS];
-unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
-unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
+unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
 atomic_t ppc_n_lost_interrupts;
 
 /* nasty hack for shared irq's since we need to do kmalloc calls but
@@ -115,52 +118,136 @@
 	kfree(ptr);
 }
 
+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;
+
+	/*
+	 * Some drivers like serial.c use request_irq() heavily,
+	 * so we have to be careful not to interfere with a
+	 * running system.
+	 */
+	if (new->flags & SA_SAMPLE_RANDOM) {
+		/*
+		 * This function might sleep, we want to call it first,
+		 * outside of the atomic block.
+		 * Yes, this might clear the entropy pool if the wrong
+		 * driver is attempted to be loaded, without actually
+		 * installing a new handler, but is this really a problem,
+		 * only the sysadmin is able to do this.
+		 */
+		rand_initialize_irq(irq);
+	}
+
+	/*
+	 * The following block of code has to be executed atomically
+	 */
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ)) {
+			spin_unlock_irqrestore(&desc->lock,flags);
+			return -EBUSY;
+		}
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	*p = new;
+
+	if (!shared) {
+		desc->depth = 0;
+		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
+		unmask_irq(irq);
+	}
+	spin_unlock_irqrestore(&desc->lock,flags);
+
+	register_irq_proc(irq);
+	return 0;
+}
+
+/* This could be promoted to a real free_irq() ... */
+static int
+do_free_irq(int irq, void* dev_id)
+{
+	irq_desc_t *desc;
+	struct irqaction **p;
+	unsigned long flags;
+
+	desc = irq_desc + irq;
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	for (;;) {
+		struct irqaction * action = *p;
+		if (action) {
+			struct irqaction **pp = p;
+			p = &action->next;
+			if (action->dev_id != dev_id)
+				continue;
+
+			/* Found it - now remove it from the list of entries */
+			*pp = action->next;
+			if (!desc->action) {
+				desc->status |= IRQ_DISABLED;
+				mask_irq(irq);
+			}
+			spin_unlock_irqrestore(&desc->lock,flags);
+
+#ifdef CONFIG_SMP
+			/* Wait to make sure it's not being used on another CPU */
+			while (desc->status & IRQ_INPROGRESS)
+				barrier();
+#endif
+			irq_kfree(action);
+			return 0;
+		}
+		printk("Trying to free free IRQ%d\n",irq);
+		spin_unlock_irqrestore(&desc->lock,flags);
+		break;
+	}
+	return -ENOENT;
+}
+
 #if (defined(CONFIG_8xx) || defined(CONFIG_8260))
 /* Name change so we can catch standard drivers that potentially mess up
  * the internal interrupt controller on 8xx and 8260.  Just bear with me,
  * I don't like this either and I am searching a better solution.  For
  * now, this is what I need. -- Dan
  */
-int request_8xxirq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+#define request_irq	request_8xxirq
 #elif defined(CONFIG_APUS)
-int request_sysirq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-#else
-int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+#define request_irq	request_sysirq
+#define free_irq	sys_free_irq
 #endif
+
+int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
 	unsigned long irqflags, const char * devname, void *dev_id)
 {
-	struct irqaction *old, **p, *action;
-	unsigned long flags;
+	struct irqaction *action;
+	int retval;
 
 	if (irq >= NR_IRQS)
 		return -EINVAL;
 	if (!handler)
-	{
-		/* Free */
-		p = &irq_desc[irq].action;
-		while ((action = *p) != NULL && action->dev_id != dev_id)
-			p = &action->next;
-		if (action == NULL)
-			return -ENOENT;
-
-		/* Found it - now free it */
-		save_flags(flags);
-		cli();
-		*p = action->next;
-		if (irq_desc[irq].action == NULL)
-			disable_irq(irq);
-		restore_flags(flags);
-		irq_kfree(action);
-		return 0;
-	}
+		/* We could implement really free_irq() instead of that... */
+		return do_free_irq(irq, dev_id);
 	
 	action = (struct irqaction *)
 		irq_kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-	if (!action)
+	if (!action) {
+		printk(KERN_ERR "irq_kmalloc() failed for irq %d !\n", irq);
 		return -ENOMEM;
-	
-	save_flags(flags);
-	cli();
+	}
 	
 	action->handler = handler;
 	action->flags = irqflags;					
@@ -168,57 +255,109 @@
 	action->name = devname;
 	action->dev_id = dev_id;
 	action->next = NULL;
-	enable_irq(irq);
 	
-	p = &irq_desc[irq].action;
-	
-	if ((old = *p) != NULL) {
-		/* Can't share interrupts unless both agree to */
-		if (!(old->flags & action->flags & SA_SHIRQ))
-			return -EBUSY;
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-	}
-	*p = action;
-
-	restore_flags(flags);	
+	retval = setup_irq(irq, action);
+	if (retval)
+		kfree(action);
+		
 	return 0;
 }
 
-#ifdef CONFIG_APUS
-void sys_free_irq(unsigned int irq, void *dev_id)
-{
-	sys_request_irq(irq, NULL, 0, NULL, dev_id);
-}
-#else
 void free_irq(unsigned int irq, void *dev_id)
 {
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
-	request_8xxirq(irq, NULL, 0, NULL, dev_id);
-#else
 	request_irq(irq, NULL, 0, NULL, dev_id);
-#endif
 }
-#endif
 
-/* XXX should implement irq disable depth like on intel */
-void disable_irq_nosync(unsigned int irq_nr)
+/*
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock. 
+ */
+ 
+/**
+ *	disable_irq_nosync - disable an irq without waiting
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line. Disables of an interrupt
+ *	stack. Unlike disable_irq(), this function does not ensure existing
+ *	instances of the IRQ handler have completed before returning.
+ *
+ *	This function may be called from IRQ context.
+ */
+ 
+ void disable_irq_nosync(unsigned int irq)
 {
-	mask_irq(irq_nr);
+	irq_desc_t *desc = irq_desc + irq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	if (!desc->depth++) {
+		if (!(desc->status & IRQ_PER_CPU))
+			desc->status |= IRQ_DISABLED;
+		mask_irq(irq);
+	}
+	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
-void disable_irq(unsigned int irq_nr)
+/**
+ *	disable_irq - disable an irq and wait for completion
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line. Disables of an interrupt
+ *	stack. That is for two disables you need two enables. This
+ *	function waits for any pending IRQ handlers for this interrupt
+ *	to complete before returning. If you use this function while
+ *	holding a resource the IRQ handler may need you will deadlock.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
+ 
+void disable_irq(unsigned int irq)
 {
-	mask_irq(irq_nr);
-	synchronize_irq();
+	disable_irq_nosync(irq);
+
+	if (!local_irq_count(smp_processor_id())) {
+		do {
+			barrier();
+		} while (irq_desc[irq].status & IRQ_INPROGRESS);
+	}
 }
 
-void enable_irq(unsigned int irq_nr)
+/**
+ *	enable_irq - enable interrupt handling on an irq
+ *	@irq: Interrupt to enable
+ *
+ *	Re-enables the processing of interrupts on this IRQ line
+ *	providing no disable_irq calls are now in effect.
+ *
+ *	This function may be called from IRQ context.
+ */
+ 
+void enable_irq(unsigned int irq)
 {
-	unmask_irq(irq_nr);
+	irq_desc_t *desc = irq_desc + irq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	switch (desc->depth) {
+	case 1: {
+		unsigned int status = desc->status & ~IRQ_DISABLED;
+		desc->status = status;
+		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+			desc->status = status | IRQ_REPLAY;
+			hw_resend_irq(desc->handler,irq);
+		}
+		unmask_irq(irq);
+		/* fall-through */
+	}
+	default:
+		desc->depth--;
+		break;
+	case 0:
+		printk("enable_irq(%u) unbalanced\n", irq);
+	}
+	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
 int get_irq_list(char *buf)
@@ -257,15 +396,41 @@
 		}
 		len += sprintf(buf+len, "\n");
 	}
+#ifdef CONFIG_TAU
+	len += sprintf(buf+len, "TAU: ");
+	for (j = 0; j < smp_num_cpus; j++)
+		len += sprintf(buf+len, "%10u ",
+				tau_interrupts(j));
+	len += sprintf(buf+len, "\n");
+#endif
 #ifdef CONFIG_SMP
 	/* should this be per processor send/receive? */
-	len += sprintf(buf+len, "IPI: %10lu\n", ipi_count);
+	len += sprintf(buf+len, "IPI (recv/sent): %10u/%u\n",
+		       atomic_read(&ipi_recv), atomic_read(&ipi_sent));
 #endif		
 	len += sprintf(buf+len, "BAD: %10u\n", ppc_spurious_interrupts);
 	return len;
 #endif /* CONFIG_APUS */
 }
 
+static inline void
+handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action)
+{
+	int status = 0;
+
+	if (!(action->flags & SA_INTERRUPT))
+		__sti();
+
+	do {
+		status |= action->flags;
+		action->handler(irq, action->dev_id, regs);
+		action = action->next;
+	} while (action);
+	if (status & SA_SAMPLE_RANDOM)
+		add_interrupt_randomness(irq);
+	__cli();
+}
+
 /*
  * Eventually, this should take an array of interrupts and an array size
  * so it can dispatch multiple interrupts.
@@ -275,33 +440,87 @@
 	int status;
 	struct irqaction *action;
 	int cpu = smp_processor_id();
+	irq_desc_t *desc = irq_desc + irq;
 
-	mask_and_ack_irq(irq);
-	status = 0;
-	action = irq_desc[irq].action;
 	kstat.irqs[cpu][irq]++;
-	if (action && action->handler) {
-		if (!(action->flags & SA_INTERRUPT))
-			__sti();
-		do { 
-			status |= action->flags;
-			action->handler(irq, action->dev_id, regs);
-			action = action->next;
-		} while ( action );
-		__cli();
-		if (irq_desc[irq].handler) {
-			if (irq_desc[irq].handler->end)
-				irq_desc[irq].handler->end(irq);
-			else if (irq_desc[irq].handler->enable)
-				irq_desc[irq].handler->enable(irq);
-		}
-	} else {
-		ppc_spurious_interrupts++;
-		printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq);
-		disable_irq(irq);
+	spin_lock(&desc->lock);
+	ack_irq(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);
+	if (!(status & IRQ_PER_CPU))
+		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;
+		if (!action || !action->handler) {
+			ppc_spurious_interrupts++;
+			printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq);
+			/* We can't call disable_irq here, it would deadlock */
+			if (!desc->depth)
+				desc->depth = 1;
+			desc->status |= IRQ_DISABLED;
+			/* This is not a real spurrious interrupt, we
+			 * have to eoi it, so we jump to out
+			 */
+			mask_irq(irq);
+			goto out;
+		}
+		status &= ~IRQ_PENDING; /* we commit to handling */
+		if (!(status & IRQ_PER_CPU))
+			status |= IRQ_INPROGRESS; /* we are handling it */
+	}
+	desc->status = status;
+
+	/*
+	 * 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.
+	 */
+	if (irq_desc[irq].handler) {
 		if (irq_desc[irq].handler->end)
 			irq_desc[irq].handler->end(irq);
+		else if (irq_desc[irq].handler->enable)
+			irq_desc[irq].handler->enable(irq);
 	}
+	spin_unlock(&desc->lock);
 }
 
 int do_IRQ(struct pt_regs *regs, int isfake)
@@ -320,6 +539,7 @@
 		{
 			printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
 			       irq, regs->nip);
+			/* That's not SMP safe ... but who cares ? */
 			ppc_spurious_interrupts++;
 		}
 		goto out;
@@ -362,7 +582,7 @@
 
 #ifdef CONFIG_SMP
 unsigned char global_irq_holder = NO_PROC_ID;
-unsigned volatile int global_irq_lock;
+unsigned volatile long global_irq_lock; /* pendantic :long for set_bit--RR*/
 atomic_t global_irq_count;
 
 atomic_t global_bh_count;
@@ -634,7 +854,11 @@
 static struct proc_dir_entry * irq_dir [NR_IRQS];
 static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
 
+#ifdef CONFIG_IRQ_ALL_CPUS
 unsigned int irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = 0xffffffff};
+#else  /* CONFIG_IRQ_ALL_CPUS */
+unsigned int irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = 0x00000000};
+#endif /* CONFIG_IRQ_ALL_CPUS */
 
 #define HEX_DIGITS 8
 
@@ -694,6 +918,7 @@
 
 	err = parse_hex_value(buffer, count, &new_value);
 
+/* Why is this disabled ? --BenH */
 #if 0/*CONFIG_SMP*/
 	/*
 	 * Do not allow disabling IRQs completely - it's a too easy
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/local_irq.h linux/arch/ppc/kernel/local_irq.h
--- v2.4.0/linux/arch/ppc/kernel/local_irq.h	Fri Aug  4 16:15:37 2000
+++ linux/arch/ppc/kernel/local_irq.h	Mon Jan 22 15:41:15 2001
@@ -15,8 +15,5 @@
 extern int ppc_spurious_interrupts;
 extern int ppc_second_irq;
 extern struct irqaction *ppc_irq_action[NR_IRQS];
-extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
-extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
-extern atomic_t ppc_n_lost_interrupts;
 
 #endif /* _PPC_KERNEL_LOCAL_IRQ_H */
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/m8260_setup.c linux/arch/ppc/kernel/m8260_setup.c
--- v2.4.0/linux/arch/ppc/kernel/m8260_setup.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/m8260_setup.c	Mon Jan 22 15:41:15 2001
@@ -62,7 +62,7 @@
 extern void mackbd_init_hw(void);
 #endif
 
-extern unsigned long loops_per_sec;
+extern unsigned long loops_per_jiffy;
 
 unsigned char __res[sizeof(bd_t)];
 unsigned long empty_zero_page[1024];
@@ -286,10 +286,7 @@
         ppc_ide_md.outsw = m8xx_ide_outsw;
         ppc_ide_md.default_irq = m8xx_ide_default_irq;
         ppc_ide_md.default_io_base = m8xx_ide_default_io_base;
-        ppc_ide_md.check_region = m8xx_ide_check_region;
-        ppc_ide_md.request_region = m8xx_ide_request_region;
-        ppc_ide_md.release_region = m8xx_ide_release_region;
-        ppc_ide_md.fix_driveid = m8xx_ide_fix_driveid;
+        ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid;
         ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports;
         ppc_ide_md.ide_request_irq = m8xx_ide_request_irq;
 
@@ -297,13 +294,39 @@
 #endif		
 }
 
-void
+/*
+ * Copied from prom.c so I don't have include all of that crap.
+ *				-- Dan
+ *
+ * prom_init() is called very early on, before the kernel text
+ * and data have been mapped to KERNELBASE.  At this point the code
+ * is running at whatever address it has been loaded at, so
+ * references to extern and static variables must be relocated
+ * explicitly.  The procedure reloc_offset() returns the address
+ * we're currently running at minus the address we were linked at.
+ * (Note that strings count as static variables.)
+ */
+extern unsigned long reloc_offset(void);
+#define PTRRELOC(x)	((typeof(x))((unsigned long)(x) + offset))
+
+__init
+unsigned long
 prom_init(uint r3, uint r4, uint r5, uint r6)
 {
-	/* Nothing to do now, but we are called immediatedly upon
-	 * kernel start up with MMU disabled, so if there is
-	 * anything we need to do......
-	 */
+	unsigned long offset = reloc_offset();
+ 	unsigned long phys;
+	extern char __bss_start, _end;
+
+	/* First zero the BSS -- use memset, some arches don't have
+	 * caches on yet */
+	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
+
+ 	/* Default */
+ 	phys = offset + KERNELBASE;
+
+	/* We are done.
+	*/
+	return phys;
 }
 
 /* Mainly for ksyms.
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- v2.4.0/linux/arch/ppc/kernel/m8xx_setup.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/m8xx_setup.c	Mon Jan 22 15:41:15 2001
@@ -63,8 +63,6 @@
 extern void mackbd_init_hw(void);
 #endif
 
-extern unsigned long loops_per_sec;
-
 unsigned char __res[sizeof(bd_t)];
 unsigned long empty_zero_page[1024];
 
@@ -344,25 +342,6 @@
 }
 
 int
-m8xx_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-        return 0;
-}
-
-void
-m8xx_ide_request_region(ide_ioreg_t from,
-			unsigned int extent,
-			const char *name)
-{
-}
-
-void
-m8xx_ide_release_region(ide_ioreg_t from,
-			unsigned int extent)
-{
-}
-
-int
 m8xx_ide_request_irq(unsigned int irq,
 		       void (*handler)(int, void *, struct pt_regs *),
 		       unsigned long flags, 
@@ -376,12 +355,6 @@
 #endif
 }
 
-void
-m8xx_ide_fix_driveid(struct hd_driveid *id)
-{
-        ppc_generic_ide_fix_driveid(id);
-}
-
 /* We can use an external IDE controller or wire the IDE interface to
  * the internal PCMCIA controller.
  */
@@ -515,10 +488,7 @@
         ppc_ide_md.outsw = m8xx_ide_outsw;
         ppc_ide_md.default_irq = m8xx_ide_default_irq;
         ppc_ide_md.default_io_base = m8xx_ide_default_io_base;
-        ppc_ide_md.check_region = m8xx_ide_check_region;
-        ppc_ide_md.request_region = m8xx_ide_request_region;
-        ppc_ide_md.release_region = m8xx_ide_release_region;
-        ppc_ide_md.fix_driveid = m8xx_ide_fix_driveid;
+        ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid;
         ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports;
         ppc_ide_md.ide_request_irq = m8xx_ide_request_irq;
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.4.0/linux/arch/ppc/kernel/misc.S	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/kernel/misc.S	Mon Jan 22 15:41:15 2001
@@ -37,6 +37,14 @@
 
 	.text
 
+	.align	5
+_GLOBAL(__delay)
+	cmpwi	0,r3,0
+	mtctr	r3
+	beqlr
+1:	bdnz	1b
+	blr
+
 /*
  * Returns (address we're running at) - (address we were linked at)
  * for use before the text and data are mapped to KERNELBASE.
@@ -82,16 +90,16 @@
 	lwz	r7,ppc_n_lost_interrupts@l(r7)
 	cmpi	0,r7,0		/* lost interrupts to process first? */
 	bne-	do_lost_interrupts
-1:	sync
+1:	SYNC
 	mtmsr	r3
-	isync
+	SYNC
 	blr
 	
 _GLOBAL(__no_use_cli)
 	mfmsr	r0		/* Get current interrupt state */
 	rlwinm	r3,r0,16+1,32-1,31	/* Extract old value of 'EE' */
 	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
-	sync			/* Some chip revs have problems here... */
+	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0		/* Update machine state */
 	blr			/* Done */
 
@@ -102,7 +110,7 @@
 	ori	r3,r3,MSR_EE	/* Turn on 'EE' bit */
 	cmpi	0,r4,0		/* lost interrupts to process first? */
 	bne-	do_lost_interrupts
-	sync			/* Some chip revs have problems here... */
+	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r3		/* Update machine state */
 	blr
 
@@ -121,7 +129,7 @@
 	cmpi	0,r4,0
 	bne-	1b
 	lwz	r3,8(r1)
-	sync
+	SYNC
 	mtmsr	r3
 	lwz	r0,20(r1)
 	mtlr	r0
@@ -137,8 +145,9 @@
 	mfmsr	r0		/* Get current msr */
 	andc	r0,r0,r3	/* And off the bits set in r3 (first parm) */
 	or	r0,r0,r4		/* Or on the bits in r4 (second parm) */
-	sync			/* Some chip revs have problems here... */
+	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0		/* Update machine state */
+	isync
 	blr			/* Done */
 
 
@@ -148,7 +157,7 @@
 _GLOBAL(_tlbia)
 #if defined(CONFIG_SMP)
 	mfmsr	r10
-	sync
+	SYNC
 	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
 	mtmsr	r0
 	SYNC
@@ -161,7 +170,6 @@
 	bne-	10b
 	stwcx.	r8,0,r9
 	bne-	10b
-	eieio
 #endif /* CONFIG_SMP */
 	sync
 	tlbia
@@ -182,7 +190,7 @@
 _GLOBAL(_tlbie)
 #if defined(CONFIG_SMP)
 	mfmsr	r10
-	sync
+	SYNC
 	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
 	mtmsr	r0
 	SYNC
@@ -228,7 +236,7 @@
 	ori	r3,r3,HID0_ICFI
 	mtspr	HID0,r3
 #endif /* CONFIG_8xx */
-	SYNC
+	isync
 	blr
 
 /*
@@ -259,7 +267,6 @@
 2:	icbi	0,r6
 	addi	r6,r6,CACHE_LINE_SIZE
 	bdnz	2b
-	sync
 	isync
 	blr
 
@@ -717,6 +724,8 @@
 	mr	r3,r1		/* Close enough */
 	blr
 
+#if 0
+/* isn't it just easier to use the mtspr/mfspr inline macros?? --Troy */
 _GLOBAL(_get_THRM1)
 	mfspr	r3,THRM1
 	blr
@@ -740,6 +749,7 @@
 _GLOBAL(_set_THRM3)
 	mtspr	THRM3,r3
 	blr
+#endif
 	
 _GLOBAL(_get_PVR)
 	mfspr	r3,PVR
@@ -755,6 +765,12 @@
 	mfspr	r3,HID0
 	blr
 
+_GLOBAL(_set_HID0)
+	sync
+	mtspr	HID0, r3
+	SYNC		/* Handle erratas in some cases */
+	blr
+
 _GLOBAL(_get_ICTC)
 	mfspr	r3,ICTC
 	blr
@@ -763,7 +779,6 @@
 	mtspr	ICTC,r3
 	blr
 
-	
 /*
 	L2CR functions
 	Copyright © 1997-1998 by PowerLogix R & D, Inc.
@@ -785,6 +800,17 @@
 /*
 	Thur, Dec. 12, 1998.
 	- First public release, contributed by PowerLogix.
+	***********
+	Sat, Aug. 7, 1999.
+	- Terry: Made sure code disabled interrupts before running. (Previously
+			it was assumed interrupts were already disabled).
+	- Terry: Updated for tentative G4 support.  4MB of memory is now flushed
+			instead of 2MB.  (Prob. only 3 is necessary).
+	- Terry: Updated for workaround to HID0[DPM] processor bug
+			during global invalidates.
+	***********
+	Thu, July 13, 2000.
+	- Terry: Added isync to correct for an errata.
 	
 	Author:	Terry Greeniaus (tgree@phys.ualberta.ca)
 	Please e-mail updates to this file to me, thanks!
@@ -823,82 +849,94 @@
 	causes cache pushes from the L1 cache to go to the L2 cache
 	instead of to main memory.
 */
-
+/*
+ * Summary: this procedure ignores the L2I bit in the value passed in,
+ * flushes the cache if it was already enabled, always invalidates the
+ * cache, then enables the cache if the L2E bit is set in the value
+ * passed in.
+ *   -- paulus.
+ */
 _GLOBAL(_set_L2CR)
-	/* Make sure this is a 750 chip */
+	/* Make sure this is a 750 or 7400 chip */
 	mfspr	r4,PVR
 	rlwinm	r4,r4,16,16,31
-	cmplwi	r4,0x0008
-	beq	thisIs750
-	cmplwi	r4,0x000c
-	beq thisIs750
-	li	r3,-1
-	blr
-	
-thisIs750:
-	/* Get the current enable bit of the L2CR into r4 */
-	mfspr	r4,L2CR
-	mfmsr	r7
-	
-	/* See if we want to perform a global inval this time. */
-	rlwinm	r6,r3,0,10,10	/* r6 contains the new invalidate bit */
-	rlwinm.	r5,r3,0,0,0	/* r5 contains the new enable bit */
-	rlwinm	r3,r3,0,11,9	/* Turn off the invalidate bit */
-	rlwimi	r3,r4,0,0,0	/* Keep the enable bit the same as it was. */
-	bne	dontDisableCache /* Only disable the cache if L2CRApply
-				    has the enable bit off */
-
-disableCache:
-	/* Disable the cache.  First, we turn off interrupts.
-	   An interrupt while we are flushing the cache could bring
-	   in data which may not get properly flushed. */
-	rlwinm	r4,r7,0,17,15	/* Turn off EE bit */
+	cmpwi	r4,0x0008
+	cmpwi	cr1,r4,0x000c
+	cror	2,2,4*cr1+2
+	bne	99f
+
+	/* Turn off interrupts and data relocation. */
+	mfmsr	r7		/* Save MSR in r7 */
+	rlwinm	r4,r7,0,17,15
+	rlwinm	r4,r4,0,28,26	/* Turn off DR bit */
 	sync
 	mtmsr	r4
-	sync
+	isync
+
+	/* Get the current enable bit of the L2CR into r4 */
+	mfspr	r4,L2CR
 	
-/*
-	Now, read the first 2MB of memory to put new data in the cache.
-	(Actually we only need the size of the L2 cache plus the size
-	of the L1 cache, but 2MB will cover everything just to be safe).
-*/
-	lis	r4,0x0001
+	/* Tweak some bits */
+	rlwinm	r5,r3,0,0,0		/* r5 contains the new enable bit */
+	rlwinm	r3,r3,0,11,9		/* Turn off the invalidate bit */
+	rlwinm	r3,r3,0,1,31		/* Turn off the enable bit */
+
+	/* Check to see if we need to flush */
+	rlwinm.	r4,r4,0,0,0
+	beq	2f
+
+	/* Flush the cache. First, read the first 4MB of memory (physical) to
+	 * put new data in the cache.  (Actually we only need
+	 * the size of the L2 cache plus the size of the L1 cache, but 4MB will
+	 * cover everything just to be safe).
+	 */
+		
+	 /**** Might be a good idea to set L2DO here - to prevent instructions
+	       from getting into the cache.  But since we invalidate
+	       the next time we enable the cache it doesn't really matter.
+	  ****/
+
+	lis	r4,0x0002
 	mtctr	r4
-	lis	r4,KERNELBASE@h
-1:	lwzx	r0,r0,r4
-	addi	r4,r4,0x0020		/* Go to start of next cache line */
+	li	r4,0
+1:
+	lwzx	r0,r0,r4
+	addi	r4,r4,32		/* Go to start of next cache line */
 	bdnz	1b
 	
-	/* Now, flush the first 2MB of memory */
-	lis	r4,0x0001
+	/* Now, flush the first 4MB of memory */
+	lis	r4,0x0002
 	mtctr	r4
-	lis	r4,KERNELBASE@h
+	li	r4,0
 	sync
-2:	dcbf	r0,r4
-	addi	r4,r4,0x0020	/* Go to start of next cache line */
-	bdnz	2b
-	
-	/* Turn off the L2CR enable bit. */
-	rlwinm	r3,r3,0,1,31
-	
-dontDisableCache:
-	/* Set up the L2CR configuration bits */
+1:
+	dcbf	r0,r4
+	addi	r4,r4,32		/* Go to start of next cache line */
+	bdnz	1b
+
+2:
+	/* Set up the L2CR configuration bits (and switch L2 off) */
 	sync
 	mtspr	L2CR,r3
 	sync
 
-	/* Reenable interrupts if necessary. */
-	mtmsr	r7
+	/* Before we perform the global invalidation, we must disable dynamic
+	 * power management via HID0[DPM] to work around a processor bug where
+	 * DPM can possibly interfere with the state machine in the processor
+	 * that invalidates the L2 cache tags.
+	 */
+	mfspr	r8,HID0			/* Save HID0 in r8 */
+	rlwinm	r4,r8,0,12,10		/* Turn off HID0[DPM] */
 	sync
-	
-	cmplwi	r6,0
-	beq	noInval
-	
+	mtspr	HID0,r4			/* Disable DPM */
+	sync
+
 	/* Perform a global invalidation */
 	oris	r3,r3,0x0020
 	sync
 	mtspr	L2CR,r3
 	sync
+	isync				/* For errata */
 
 	/* Wait for the invalidation to complete */
 3:	mfspr	r3,L2CR
@@ -910,27 +948,38 @@
 	mtspr	L2CR,r3
 	sync
 	
-noInval:
+	/* Restore HID0[DPM] to whatever it was before */
+	sync
+	mtspr	1008,r8
+	sync
+
 	/* See if we need to enable the cache */
 	cmplwi	r5,0
-	beqlr
+	beq	4f
 
 	/* Enable the cache */
 	oris	r3,r3,0x8000
 	mtspr	L2CR,r3
 	sync
+
+	/* Restore MSR (restores EE and DR bits to original state) */
+4:	SYNC
+	mtmsr	r7
+	isync
+	blr
+
+99:	li	r3,-1
 	blr
 
 _GLOBAL(_get_L2CR)
 	/* Make sure this is a 750 chip */
 	mfspr	r3,PVR
-	rlwinm	r3,r3,16,16,31
-	cmplwi	r3,0x0008
-	beq	1f
-	cmplwi	r3,0x000c
+	srwi	r3,r3,16
+	cmpwi	r3,0x0008
+	cmpwi	cr1,r3,0x000c
 	li	r3,0
+	cror	2,2,4*cr1+2
 	bnelr
-1:	
 	/* Return the L2CR contents */
 	mfspr	r3,L2CR
 	blr
@@ -986,15 +1035,6 @@
 	blr
 #endif
 
-_GLOBAL(__clear_msr_me)
-        mfmsr   r0                      /* Get current interrupt state */
-        lis     r3,0
-        ori     r3,r3,MSR_ME
-        andc    r0,r0,r3                /* Clears bit in (r4) */
-        sync                            /* Some chip revs have problems here */
-        mtmsr   r0                      /* Update machine state */
-        blr
-
 /*
  * Create a kernel thread
  *   kernel_thread(fn, arg, flags)
@@ -1244,16 +1284,20 @@
 	.long sys_getrlimit	/* 190 */
 	.long sys_ni_syscall		/* 191 */	/* Unused */
 	.long sys_ni_syscall		/* 192 - reserved - mmap2 */
-	.long sys_ni_syscall		/* 193 - reserved - truncate64 */
-	.long sys_ni_syscall		/* 194 - reserved - ftruncate64 */
-	.long sys_ni_syscall		/* 195 - reserved - stat64 */
-	.long sys_ni_syscall		/* 196 - reserved - lstat64 */
-	.long sys_ni_syscall		/* 197 - reserved - fstat64 */
+	.long sys_truncate64		/* 193 */
+	.long sys_ftruncate64		/* 194 */
+	.long sys_stat64		/* 195 */
+	.long sys_lstat64		/* 196 */
+	.long sys_fstat64		/* 197 */
 	.long sys_pciconfig_read	/* 198 */
 	.long sys_pciconfig_write 	/* 199 */
 	.long sys_pciconfig_iobase 	/* 200 */
 	.long sys_ni_syscall		/* 201 - reserved - MacOnLinux - new */
 	.long sys_getdents64		/* 202 */
+	.long sys_pivot_root		/* 203 */
+	.long sys_fcntl64		/* 204 */
+	.long sys_madvise		/* 205 */
+	.long sys_mincore		/* 206 */
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long sys_ni_syscall
 	.endr
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- v2.4.0/linux/arch/ppc/kernel/open_pic.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/open_pic.c	Mon Jan 22 15:41:15 2001
@@ -1,5 +1,5 @@
 /*
- *  arch/ppc/kernel/openpic.c -- OpenPIC Interrupt Handling
+ *  arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
  *
  *  Copyright (C) 1997 Geert Uytterhoeven
  *
@@ -13,35 +13,38 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/openpic.h>
+#include <linux/irq.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
+
 #include "local_irq.h"
+#include "open_pic.h"
+#include "open_pic_defs.h"
 
-volatile struct OpenPIC *OpenPIC = NULL;
+void* OpenPIC_Addr;
+static volatile struct OpenPIC *OpenPIC = NULL;
 u_int OpenPIC_NumInitSenses __initdata = 0;
 u_char *OpenPIC_InitSenses __initdata = NULL;
-int open_pic_irq_offset;
 extern int use_of_interrupt_tree;
 
-void chrp_mask_irq(unsigned int);
-void chrp_unmask_irq(unsigned int);
 void find_ISUs(void);
 
 static u_int NumProcessors;
 static u_int NumSources;
-OpenPIC_Source *ISU;
-/*
- * We should use this if we have > 1 ISU.
- * We can just point each entry to the
- * appropriate source regs but it wastes a lot of space
- * so until we have >1 ISU I'll leave it unimplemented.
- * -- Cort
-OpenPIC_Source ISU[128];
-*/
+#ifdef CONFIG_POWER3
+static int NumISUs;
+#endif
+static int open_pic_irq_offset;
+static volatile unsigned char* chrp_int_ack_special;
+
+OpenPIC_SourcePtr ISU[OPENPIC_MAX_ISU];
+
+static void openpic_end_irq(unsigned int irq_nr);
+static void openpic_ack_irq(unsigned int irq_nr);
+static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask);
 
 struct hw_interrupt_type open_pic = {
 	" OpenPIC  ",
@@ -49,45 +52,69 @@
 	NULL,
 	openpic_enable_irq,
 	openpic_disable_irq,
-	0,
+	openpic_ack_irq,
+	openpic_end_irq,
+	openpic_set_affinity
+};
+
+#ifdef CONFIG_SMP
+static void openpic_end_ipi(unsigned int irq_nr);
+static void openpic_ack_ipi(unsigned int irq_nr);
+static void openpic_enable_ipi(unsigned int irq_nr);
+static void openpic_disable_ipi(unsigned int irq_nr);
+
+struct hw_interrupt_type open_pic_ipi = {
+	" OpenPIC  ",
+	NULL,
+	NULL,
+	openpic_enable_ipi,
+	openpic_disable_ipi,
+	openpic_ack_ipi,
+	openpic_end_ipi,
 	0
 };
+#endif /* CONFIG_SMP */
 
 /*
- *  Accesses to the current processor's registers
+ *  Accesses to the current processor's openpic registers
  */
-#ifndef __powerpc__
-#define THIS_CPU		Private
-#define CHECK_THIS_CPU		do {} while (0)
-#else
+#ifdef CONFIG_SMP
 #define THIS_CPU		Processor[cpu]
+#define DECL_THIS_CPU		int cpu = smp_hw_index[smp_processor_id()]
 #define CHECK_THIS_CPU		check_arg_cpu(cpu)
-#endif
+#else
+#define THIS_CPU		Processor[0]
+#define DECL_THIS_CPU
+#define CHECK_THIS_CPU
+#endif /* CONFIG_SMP */
 
 #if 1
 #define check_arg_ipi(ipi) \
     if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
-	printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi);
+	printk("open_pic.c:%d: illegal ipi %d\n", __LINE__, ipi);
 #define check_arg_timer(timer) \
     if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
-	printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer);
+	printk("open_pic.c:%d: illegal timer %d\n", __LINE__, timer);
 #define check_arg_vec(vec) \
     if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
-	printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec);
+	printk("open_pic.c:%d: illegal vector %d\n", __LINE__, vec);
 #define check_arg_pri(pri) \
     if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
-	printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri);
+	printk("open_pic.c:%d: illegal priority %d\n", __LINE__, pri);
 /*
- * I changed this to return to keep us from from trying to use irq #'s
- * that we're using for IPI's.
- *   -- Cort
- */ 
+ * Print out a backtrace if it's out of range, since if it's larger than NR_IRQ's
+ * data has probably been corrupted and we're going to panic or deadlock later
+ * anyway --Troy
+ */
+extern unsigned long* _get_SP(void);
 #define check_arg_irq(irq) \
-    /*if (irq < 0 || irq >= (NumSources+open_pic_irq_offset)) \
-      printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);*/
+    if (irq < open_pic_irq_offset || irq >= (NumSources+open_pic_irq_offset)){ \
+      printk("open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \
+      print_backtrace(_get_SP()); }
 #define check_arg_cpu(cpu) \
-    if (cpu < 0 || cpu >= NumProcessors) \
-	printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu);
+    if (cpu < 0 || cpu >= NumProcessors){ \
+	printk("open_pic.c:%d: illegal cpu %d\n", __LINE__, cpu); \
+	print_backtrace(_get_SP()); }
 #else
 #define check_arg_ipi(ipi)	do {} while (0)
 #define check_arg_timer(timer)	do {} while (0)
@@ -97,23 +124,10 @@
 #define check_arg_cpu(cpu)	do {} while (0)
 #endif
 
-#ifdef CONFIG_SMP
-void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
-	smp_message_recv(cpl-OPENPIC_VEC_IPI, regs);
-}
-#endif /* CONFIG_SMP */
-
-#ifdef __i386__
-static inline u_int in_le32(volatile u_int *addr)
-{
-	return *addr;
-}
-
-static inline void out_le32(volatile u_int *addr, u_int val)
-{
-	*addr = val;
-}
+#ifdef CONFIG_POWER3
+	#define GET_ISU(source)	ISU[(source) >> 4][(source) & 0xf]
+#else
+	#define GET_ISU(source)	ISU[0][(source)]
 #endif
 
 u_int openpic_read(volatile u_int *addr)
@@ -156,22 +170,66 @@
 				    u_int field)
 {
 	openpic_setfield(addr, OPENPIC_MASK);
-	/* wait until it's not in use */
-	/* BenH: Is this code really enough ? I would rather check the result
-	 *       and eventually retry ...
-	 */
 	while (openpic_read(addr) & OPENPIC_ACTIVITY);
 	openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
 }
 
-void __init openpic_init(int main_pic)
+#ifdef CONFIG_SMP
+/* yes this is right ... bug, feature, you decide! -- tgall */
+u_int openpic_read_IPI(volatile u_int* addr)
+{
+         u_int val = 0;
+#ifdef CONFIG_POWER3
+        val = in_be32(addr);
+#else
+        val = in_le32(addr);
+#endif
+        return val;
+}
+
+/* because of the power3 be / le above, this is needed */
+inline void openpic_writefield_IPI(volatile u_int* addr, u_int mask, u_int field)
+{
+        u_int  val = openpic_read_IPI(addr);
+        openpic_write(addr, (val & ~mask) | (field & mask));
+}
+
+static inline void openpic_clearfield_IPI(volatile u_int *addr, u_int mask)
+{
+        openpic_writefield_IPI(addr, mask, 0);
+}
+
+static inline void openpic_setfield_IPI(volatile u_int *addr, u_int mask)
+{
+        openpic_writefield_IPI(addr, mask, mask);
+}
+
+static void openpic_safe_writefield_IPI(volatile u_int *addr, u_int mask, u_int field)
+{
+        openpic_setfield_IPI(addr, OPENPIC_MASK);
+
+        /* wait until it's not in use */
+        /* BenH: Is this code really enough ? I would rather check the result
+         *       and eventually retry ...
+         */
+        while(openpic_read_IPI(addr) & OPENPIC_ACTIVITY);
+
+        openpic_writefield_IPI(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
+}
+#endif /* CONFIG_SMP */
+
+void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
+			 int programmer_switch_irq)
 {
 	u_int t, i;
 	u_int timerfreq;
 	const char *version;
 
-	if (!OpenPIC)
-		panic("No OpenPIC found");
+	if (!OpenPIC_Addr) {
+		printk("No OpenPIC found !\n");
+		return;
+	}
+	OpenPIC = (volatile struct OpenPIC *)OpenPIC_Addr;
 
 	if ( ppc_md.progress ) ppc_md.progress("openpic enter",0x122);
 
@@ -194,179 +252,180 @@
 			 OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
 	NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
 		      OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
-	if ( _machine != _MACH_Pmac )
-	{
-		printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version,
-		       NumProcessors, NumSources, OpenPIC);
-		timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
-		printk("OpenPIC timer frequency is ");
-		if (timerfreq)
-			printk("%d MHz\n", timerfreq>>20);
-		else
-			printk("not set\n");
+	printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n",
+	       version, NumProcessors, NumSources, OpenPIC);
+	timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
+	if (timerfreq)
+		printk("OpenPIC timer frequency is %d.%06d MHz\n",
+		       timerfreq / 1000000, timerfreq % 1000000);
+
+	if (!main_pic)
+		return;
+
+	open_pic_irq_offset = offset;
+	chrp_int_ack_special = (volatile unsigned char*)chrp_ack;
+
+	/* Initialize timer interrupts */
+	if ( ppc_md.progress ) ppc_md.progress("openpic timer",0x3ba);
+	for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
+		/* Disabled, Priority 0 */
+		openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+offset);
+		/* No processor */
+		openpic_maptimer(i, 0);
 	}
-	
-	if ( main_pic )
-	{
-		/* Initialize timer interrupts */
-		if ( ppc_md.progress ) ppc_md.progress("openpic timer",0x3ba);
-		for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
-			/* Disabled, Priority 0 */
-			openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
-			/* No processor */
-			openpic_maptimer(i, 0);
-		}
-	    
-		/* Initialize IPI interrupts */
-		if ( ppc_md.progress ) ppc_md.progress("openpic ipi",0x3bb);
-		for (i = 0; i < OPENPIC_NUM_IPI; i++) {
-			/* Disabled, Priority 8 */
-			openpic_initipi(i, 8, OPENPIC_VEC_IPI+i);
-		}
-		find_ISUs();
-		if ( _machine != _MACH_Pmac )
-		{
-			/* Initialize external interrupts */
-			if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc);
-			/* SIOint (8259 cascade) is special */
-			openpic_initirq(0, 8, open_pic_irq_offset, 1, 1);
-			openpic_mapirq(0, 1<<0);
-			for (i = 1; i < NumSources; i++) {
-				/* Enabled, Priority 8 */
-				openpic_initirq(i, 8, open_pic_irq_offset+i, 0,
-						i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
-				/* Processor 0 */
-				openpic_mapirq(i, 1<<0);
-			}
-		}
-		else
-		{
-			/* Prevent any interrupt from occuring during initialisation.
-			 * Hum... I believe this is not necessary, Apple does that in
-			 * Darwin's PowerExpress code.
-			 */
-			openpic_set_priority(0, 0xf);
-			
-			/* First disable all interrupts and map them to CPU 0 */
-			for (i = 0; i < NumSources; i++) {
-				openpic_disable_irq(i);
-				openpic_mapirq(i, 1<<0);
-			}
-			
-			/* If we use the device tree, then lookup all interrupts and
-			 * initialize them according to sense infos found in the tree
-			 */
-			if (use_of_interrupt_tree) {
-				struct device_node* np = find_all_nodes();
-			    	while(np) {
-					int j, pri;
-					pri = strcmp(np->name, "programmer-switch") ? 2 : 7;
-					for (j=0;j<np->n_intrs;j++) {
-						openpic_initirq(np->intrs[j].line,
-								pri,
-								np->intrs[j].line,
-								0,
-								np->intrs[j].sense);
-						if (np->intrs[j].sense)
-							irq_desc[np->intrs[j].line].status =  IRQ_LEVEL;
-					}
-					np = np->next;
-				}
-			}
-		}
-		
-		/* Initialize the spurious interrupt */
-		if ( ppc_md.progress ) ppc_md.progress("openpic spurious",0x3bd);
-		openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
-		if ( !(_machine & (_MACH_gemini|_MACH_Pmac)) )
-		{
-			if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
-					"82c59 cascade", NULL))
-				printk("Unable to get OpenPIC IRQ 0 for cascade\n");
-		}
-		openpic_set_priority(0, 0);
-		openpic_disable_8259_pass_through();
+
+#ifdef CONFIG_SMP
+	/* Initialize IPI interrupts */
+	if ( ppc_md.progress ) ppc_md.progress("openpic ipi",0x3bb);
+	for (i = 0; i < OPENPIC_NUM_IPI; i++) {
+		/* Disabled, Priority 10..13 */
+		openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset);
+		/* IPIs are per-CPU */
+		irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU;
+		irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi;
+	}
+#endif
+
+	find_ISUs();
+
+	/* Initialize external interrupts */
+	if (ppc_md.progress) ppc_md.progress("openpic ext",0x3bc);
+
+	openpic_set_priority(0xf);
+
+	/* SIOint (8259 cascade) is special */
+	if (offset) {
+		openpic_initirq(0, 8, offset, 1, 1);
+		openpic_mapirq(0, 1<<0);
 	}
-	if ( ppc_md.progress ) ppc_md.progress("openpic exit",0x222);
+
+	/* Init all external sources */
+	for (i = 1; i < NumSources; i++) {
+		int pri, sense;
+
+		/* the bootloader may have left it enabled (bad !) */
+		openpic_disable_irq(i+offset);
+
+		pri = (i == programmer_switch_irq)? 9: 8;
+		sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: 1;
+		if (sense)
+			irq_desc[i+offset].status = IRQ_LEVEL;
+
+		/* Enabled, Priority 8 or 9 */
+		openpic_initirq(i, pri, i+offset, !sense, sense);
+		/* Processor 0 */
+		openpic_mapirq(i, 1<<0);
+	}
+
+	/* Init descriptors */
+	for (i = offset; i < NumSources + offset; i++)
+		irq_desc[i].handler = &open_pic;
+
+	/* Initialize the spurious interrupt */
+	if (ppc_md.progress) ppc_md.progress("openpic spurious",0x3bd);
+	openpic_set_spurious(OPENPIC_VEC_SPURIOUS+offset);
+
+	/* Initialize the cascade */
+	if (offset) {
+		if (request_irq(offset, no_action, SA_INTERRUPT,
+				"82c59 cascade", NULL))
+			printk("Unable to get OpenPIC IRQ 0 for cascade\n");
+	}
+	openpic_set_priority(0);
+	openpic_disable_8259_pass_through();
+
+	if (ppc_md.progress) ppc_md.progress("openpic exit",0x222);
 }
 
+#ifdef CONFIG_POWER3
+void openpic_setup_ISU(int isu_num, unsigned long addr)
+{
+	if (isu_num >= OPENPIC_MAX_ISU)
+		return;
+	ISU[isu_num] = (OpenPIC_SourcePtr) ioremap(addr, 0x400);
+	if (isu_num >= NumISUs)
+		NumISUs = isu_num + 1;
+}
+#endif
+
 void find_ISUs(void)
 {
-#ifdef CONFIG_PPC64BRIDGE
-	/* hardcode this for now since the IBM 260 is the only thing with
-	 * a distributed openpic right now.  -- Cort
+#ifdef CONFIG_POWER3
+        /* Use /interrupt-controller/reg and
+         * /interrupt-controller/interrupt-ranges from OF device tree
+	 * the ISU array is setup in chrp_pci.c in ibm_add_bridges
+	 * as a result
+	 * -- tgall
+         */
+
+	/* basically each ISU is a bus, and this assumes that
+	 * open_pic_isu_count interrupts per bus are possible 
+	 * ISU == Interrupt Source
 	 */
-	ISU = (OpenPIC_Source *)0xfeff7c00;
-	NumSources = 0x10;
+	NumSources = NumISUs * 0x10;
+
 #else
 	/* for non-distributed OpenPIC implementations it's in the IDU -- Cort */
-	ISU = (OpenPIC_Source *)OpenPIC->Source;
+	ISU[0] = (OpenPIC_Source *)OpenPIC->Source;
 #endif
 }
 
-void openpic_reset(void)
+static inline void openpic_reset(void)
 {
 	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
 			 OPENPIC_CONFIG_RESET);
 }
 
-void openpic_enable_8259_pass_through(void)
+static inline void openpic_enable_8259_pass_through(void)
 {
 	openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
 			   OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
 }
 
-void openpic_disable_8259_pass_through(void)
+static void openpic_disable_8259_pass_through(void)
 {
 	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
 			 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
 }
 
-#ifndef __i386__
 /*
  *  Find out the current interrupt
  */
-u_int openpic_irq(u_int cpu)
+static u_int openpic_irq(void)
 {
 	u_int vec;
+	DECL_THIS_CPU;
 
-	check_arg_cpu(cpu);
+	CHECK_THIS_CPU;
 	vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
 				OPENPIC_VECTOR_MASK);
 	return vec;
 }
-#endif
 
-#ifndef __powerpc__
-void openpic_eoi(void)
-#else
-void openpic_eoi(u_int cpu)
-#endif
+static void openpic_eoi(void)
 {
-	check_arg_cpu(cpu);
+	DECL_THIS_CPU;
+
+	CHECK_THIS_CPU;
 	openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
 	/* Handle PCI write posting */
 	(void)openpic_read(&OpenPIC->THIS_CPU.EOI);
 }
 
 
-#ifndef __powerpc__
-u_int openpic_get_priority(void)
-#else
-u_int openpic_get_priority(u_int cpu)
-#endif
+static inline u_int openpic_get_priority(void)
 {
+	DECL_THIS_CPU;
+
 	CHECK_THIS_CPU;
 	return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
 				 OPENPIC_CURRENT_TASK_PRIORITY_MASK);
 }
 
-#ifndef __powerpc__
-void openpic_set_priority(u_int pri)
-#else
-void openpic_set_priority(u_int cpu, u_int pri)
-#endif
+static void openpic_set_priority(u_int pri)
 {
+	DECL_THIS_CPU;
+
 	CHECK_THIS_CPU;
 	check_arg_pri(pri);
 	openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
@@ -376,24 +435,43 @@
 /*
  *  Get/set the spurious vector
  */
-u_int openpic_get_spurious(void)
+static inline u_int openpic_get_spurious(void)
 {
 	return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
 				 OPENPIC_VECTOR_MASK);
 }
 
-void openpic_set_spurious(u_int vec)
+static void openpic_set_spurious(u_int vec)
 {
 	check_arg_vec(vec);
 	openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
 			   vec);
 }
 
+#ifdef CONFIG_SMP
+/*
+ * Convert a cpu mask from logical to physical cpu numbers.
+ */
+static inline u32 physmask(u32 cpumask)
+{
+	int i;
+	u32 mask = 0;
+
+	for (i = 0; i < smp_num_cpus; ++i, cpumask >>= 1)
+		mask |= (cpumask & 1) << smp_hw_index[i];
+	return mask;
+}
+#else
+#define physmask(cpumask)	(cpumask)
+#endif
+
 void openpic_init_processor(u_int cpumask)
 {
-	openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask);
+	openpic_write(&OpenPIC->Global.Processor_Initialization,
+		      physmask(cpumask));
 }
 
+#ifdef CONFIG_SMP
 /*
  *  Initialize an interprocessor interrupt (and disable it)
  *
@@ -401,35 +479,55 @@
  *  pri: interrupt source priority
  *  vec: the vector it will produce
  */
-void openpic_initipi(u_int ipi, u_int pri, u_int vec)
+static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
 {
-	check_arg_timer(ipi);
+	check_arg_ipi(ipi);
 	check_arg_pri(pri);
 	check_arg_vec(vec);
-	openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
+	openpic_safe_writefield_IPI(&OpenPIC->Global.IPI_Vector_Priority(ipi),
 				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
 				(pri << OPENPIC_PRIORITY_SHIFT) | vec);
 }
 
 /*
  *  Send an IPI to one or more CPUs
+ *  
+ *  Externally called, however, it takes an IPI number (0...OPENPIC_NUM_IPI)
+ *  and not a system-wide interrupt number
  */
-#ifndef __powerpc__
 void openpic_cause_IPI(u_int ipi, u_int cpumask)
-#else
-void openpic_cause_IPI(u_int cpu, u_int ipi, u_int cpumask)
-#endif
 {
+	DECL_THIS_CPU;
+
 	CHECK_THIS_CPU;
 	check_arg_ipi(ipi);
-	openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask);
+	openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
+		      physmask(cpumask));
 }
 
-void openpic_enable_IPI(u_int ipi)
+void openpic_request_IPIs(void)
 {
-	check_arg_ipi(ipi);
-	openpic_clearfield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
-			   OPENPIC_MASK);
+	int i;
+	
+	/*
+	 * Make sure this matches what is defined in smp.c for 
+	 * smp_message_{pass|recv}() or what shows up in 
+	 * /proc/interrupts will be wrong!!! --Troy */
+	
+	if (OpenPIC == NULL)
+		return;
+
+	request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset,
+		    openpic_ipi_action, 0, "IPI0 (call function)", 0);
+	request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1,
+		    openpic_ipi_action, 0, "IPI1 (reschedule)", 0);
+	request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2,
+		    openpic_ipi_action, 0, "IPI2 (invalidate tlb)", 0);
+	request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3,
+		    openpic_ipi_action, 0, "IPI3 (xmon break)", 0);
+
+	for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
+		openpic_enable_ipi(OPENPIC_VEC_IPI+open_pic_irq_offset+i);
 }
 
 /*
@@ -437,21 +535,31 @@
  *
  * Get IPI's working and start taking interrupts.
  *   -- Cort
-  */
-void do_openpic_setup_cpu(void)
+ */
+static spinlock_t openpic_setup_lock __initdata = SPIN_LOCK_UNLOCKED;
+
+void __init do_openpic_setup_cpu(void)
 {
  	int i;
- 	
- 	for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
-		openpic_enable_IPI(i);
-#if 0	
- 	/* let the openpic know we want intrs */
- 	for ( i = 0; i < NumSources ; i++ )
- 		openpic_mapirq(i, openpic_read(ISU[i].Destination)
- 			       | (1<<smp_processor_id()) );
-#endif	
- 	openpic_set_priority(smp_processor_id(), 0);
+	u32 msk = 1 << smp_hw_index[smp_processor_id()];
+
+	spin_lock(&openpic_setup_lock);
+
+#ifdef CONFIG_IRQ_ALL_CPUS
+ 	/* let the openpic know we want intrs. default affinity
+ 	 * is 0xffffffff until changed via /proc
+ 	 * That's how it's done on x86. If we want it differently, then
+ 	 * we should make sure we also change the default values of irq_affinity
+ 	 * in irq.c.
+ 	 */
+ 	for (i = 0; i < NumSources ; i++)
+		openpic_mapirq(i, openpic_read(&GET_ISU(i).Destination) | msk);
+#endif /* CONFIG_IRQ_ALL_CPUS */
+ 	openpic_set_priority(0);
+
+	spin_unlock(&openpic_setup_lock);
 }
+#endif /* CONFIG_SMP */
 
 /*
  *  Initialize a timer interrupt (and disable it)
@@ -460,7 +568,7 @@
  *  pri: interrupt source priority
  *  vec: the vector it will produce
  */
-void openpic_inittimer(u_int timer, u_int pri, u_int vec)
+static void __init openpic_inittimer(u_int timer, u_int pri, u_int vec)
 {
 	check_arg_timer(timer);
 	check_arg_pri(pri);
@@ -473,37 +581,99 @@
 /*
  *  Map a timer interrupt to one or more CPUs
  */
-void openpic_maptimer(u_int timer, u_int cpumask)
+static void __init openpic_maptimer(u_int timer, u_int cpumask)
 {
 	check_arg_timer(timer);
-	openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask);
+	openpic_write(&OpenPIC->Global.Timer[timer].Destination,
+		      physmask(cpumask));
 }
 
+
 /*
- *  Enable/disable an interrupt source
+ *
+ * All functions below take an offset'ed irq argument
+ *
  */
-void openpic_enable_irq(u_int irq)
+
+
+/*
+ *  Enable/disable an external interrupt source
+ *
+ *  Externally called, irq is an offseted system-wide interrupt number
+ */
+static void openpic_enable_irq(u_int irq)
 {
 	check_arg_irq(irq);
-	openpic_clearfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
+
+        /*
+         * Never want to disable a timer or ipi irq
+         * (only want to disable irqs within an ISU).
+         */
+        if (((irq >= OPENPIC_VEC_IPI+open_pic_irq_offset)   &&
+           (irq <  OPENPIC_VEC_IPI+open_pic_irq_offset+OPENPIC_NUM_IPI)) ||
+           ((irq >= OPENPIC_VEC_TIMER+open_pic_irq_offset) &&
+            (irq <  OPENPIC_VEC_TIMER+open_pic_irq_offset+OPENPIC_NUM_TIMERS)))
+        {
+        /* silently ignore the enable of the timer or ipi irq. */
+        return;
+        }
+
+
+	openpic_clearfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK);
 	/* make sure mask gets to controller before we return to user */
 	do {
 		mb(); /* sync is probably useless here */
-	} while(openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority,
+	} while(openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority,
 			OPENPIC_MASK));
 }
 
-void openpic_disable_irq(u_int irq)
+static void openpic_disable_irq(u_int irq)
 {
+	u32 vp;
+	
 	check_arg_irq(irq);
-	openpic_setfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
+        /*
+         * Never want to disable a timer or ipi irq
+         * (only want to disable irqs within an ISU).
+         */
+        if (((irq >= OPENPIC_VEC_IPI+open_pic_irq_offset)   &&
+             (irq <  OPENPIC_VEC_IPI+open_pic_irq_offset+OPENPIC_NUM_IPI)) ||
+             ((irq >= OPENPIC_VEC_TIMER+open_pic_irq_offset) &&
+             (irq <  OPENPIC_VEC_TIMER+open_pic_irq_offset+OPENPIC_NUM_TIMERS)))
+        {
+                panic("openpic_disable_irq - disabling non-ISU irq");
+        }
+
+
+	openpic_setfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK);
 	/* make sure mask gets to controller before we return to user */
 	do {
 		mb();  /* sync is probably useless here */
-	} while(!openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority,
-    			OPENPIC_MASK));
+		vp = openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority,
+    			OPENPIC_MASK | OPENPIC_ACTIVITY);
+	} while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
 }
 
+#ifdef CONFIG_SMP
+/*
+ *  Enable/disable an IPI interrupt source
+ *  
+ *  Externally called, irq is an offseted system-wide interrupt number
+ */
+void openpic_enable_ipi(u_int irq)
+{
+	irq -= (OPENPIC_VEC_IPI+open_pic_irq_offset);
+	check_arg_ipi(irq);
+	openpic_clearfield_IPI(&OpenPIC->Global.IPI_Vector_Priority(irq), OPENPIC_MASK);
+
+}
+void openpic_disable_ipi(u_int irq)
+{
+   /* NEVER disable an IPI... that's just plain wrong! */
+}
+
+#endif
+
 /*
  *  Initialize an interrupt source (and disable it!)
  *
@@ -513,12 +683,9 @@
  *  pol: polarity (1 for positive, 0 for negative)
  *  sense: 1 for level, 0 for edge
  */
-void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
+static void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
 {
-	check_arg_irq(irq);
-	check_arg_pri(pri);
-	check_arg_vec(vec);
-	openpic_safe_writefield(&ISU[irq].Vector_Priority,
+	openpic_safe_writefield(&GET_ISU(irq).Vector_Priority,
 				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
 				OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
 				(pri << OPENPIC_PRIORITY_SHIFT) | vec |
@@ -530,10 +697,9 @@
 /*
  *  Map an interrupt source to one or more CPUs
  */
-void openpic_mapirq(u_int irq, u_int cpumask)
+static void openpic_mapirq(u_int irq, u_int physmask)
 {
-	check_arg_irq(irq);
-	openpic_write(&ISU[irq].Destination, cpumask);
+	openpic_write(&GET_ISU(irq).Destination, physmask);
 }
 
 /*
@@ -541,10 +707,92 @@
  *
  *  sense: 1 for level, 0 for edge
  */
-void openpic_set_sense(u_int irq, int sense)
+static inline void openpic_set_sense(u_int irq, int sense)
 {
-	check_arg_irq(irq);
-	openpic_safe_writefield(&ISU[irq].Vector_Priority,
+	openpic_safe_writefield(&GET_ISU(irq).Vector_Priority,
 				OPENPIC_SENSE_LEVEL,
 				(sense ? OPENPIC_SENSE_LEVEL : 0));
 }
+
+/* No spinlocks, should not be necessary with the OpenPIC
+ * (1 register = 1 interrupt and we have the desc lock).
+ */
+static void openpic_ack_irq(unsigned int irq_nr)
+{
+#if 1 /* masking should be unnecessary, but I still get spurrious */
+	openpic_disable_irq(irq_nr);
+#endif		
+	if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
+		openpic_eoi();
+}
+
+static void openpic_end_irq(unsigned int irq_nr)
+{
+	if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0)
+		openpic_eoi();
+	
+#if 1 /* masking should be unnecessary, but I still get spurrious */
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		openpic_enable_irq(irq_nr);
+#endif
+}
+
+static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask)
+{
+	openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask));
+}
+
+#ifdef CONFIG_SMP
+static void openpic_ack_ipi(unsigned int irq_nr)
+{
+}
+
+static void openpic_end_ipi(unsigned int irq_nr)
+{
+	/* IPIs are marked IRQ_PER_CPU. This has the side effect of
+	 * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
+	 * applying to them. We EOI them late to avoid re-entering.
+	 * however, I'm wondering if we could simply let them have the
+	 * SA_INTERRUPT flag and let them execute with all interrupts OFF.
+	 * This would have the side effect of either running cross-CPU
+	 * functions with interrupts off, or we can re-enable them explicitely
+	 * with a __sti() in smp_call_function_interrupt(), since
+	 * smp_call_function() is protected by a spinlock.
+	 * Or maybe we shouldn't set the IRQ_PER_CPU flag on cross-CPU
+	 * function calls IPI at all but that would make a special case.
+	 */
+	openpic_eoi();
+}
+
+static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+	smp_message_recv(cpl-OPENPIC_VEC_IPI-open_pic_irq_offset, regs);
+}
+
+#endif /* CONFIG_SMP */
+
+/* This one may be merged with PReP and CHRP */
+int
+openpic_get_irq(struct pt_regs *regs)
+{
+	extern int i8259_irq(int cpu);
+
+	int irq = openpic_irq();
+
+	/* Management of the cascade should be moved out of here */
+        if (open_pic_irq_offset && irq == open_pic_irq_offset)
+        {
+                /*
+                 * This magic address generates a PCI IACK cycle.
+                 */
+		if ( chrp_int_ack_special )
+			irq = *chrp_int_ack_special;
+		else
+			irq = i8259_irq( smp_processor_id() );
+		openpic_eoi();
+        }
+	if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset)
+		irq = -1;
+	return irq;
+}
+
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h
--- v2.4.0/linux/arch/ppc/kernel/open_pic.h	Mon Jan 10 18:25:06 2000
+++ linux/arch/ppc/kernel/open_pic.h	Wed Jan 24 15:28:36 2001
@@ -1,11 +1,45 @@
+/*
+ *  arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling
+ *
+ *  Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ *  
+ */
+
 #ifndef _PPC_KERNEL_OPEN_PIC_H
 #define _PPC_KERNEL_OPEN_PIC_H
 
+#include <linux/config.h>
+
+#define OPENPIC_SIZE	0x40000
+
+/* OpenPIC IRQ controller structure */
 extern struct hw_interrupt_type open_pic;
 
-void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
-void openpic_enable_IPI(u_int ipi);
-void do_openpic_setup_cpu(void);
+/* OpenPIC IPI controller structure */
+#ifdef CONFIG_SMP
+extern struct hw_interrupt_type open_pic_ipi;
+#endif /* CONFIG_SMP */
+
+extern u_int OpenPIC_NumInitSenses;
+extern u_char *OpenPIC_InitSenses;
+extern void* OpenPIC_Addr;
+
+/* Exported functions */
+extern void openpic_init(int, int, unsigned char *, int);
+extern void openpic_request_IPIs(void);
+extern void do_openpic_setup_cpu(void);
+extern int openpic_get_irq(struct pt_regs *regs);
+extern void openpic_init_processor(u_int cpumask);
+extern void openpic_setup_ISU(int isu_num, unsigned long addr);
+extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
 
-extern int open_pic_irq_offset;
+extern inline int openpic_to_irq(int irq)
+{
+	return irq += NUM_8259_INTERRUPTS;
+}
+/*extern int open_pic_irq_offset;*/
 #endif /* _PPC_KERNEL_OPEN_PIC_H */
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/open_pic_defs.h linux/arch/ppc/kernel/open_pic_defs.h
--- v2.4.0/linux/arch/ppc/kernel/open_pic_defs.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/open_pic_defs.h	Mon Jan 22 15:41:15 2001
@@ -0,0 +1,328 @@
+/*
+ *  linux/openpic.h -- OpenPIC definitions
+ *
+ *  Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is based on the following documentation:
+ *
+ *	The Open Programmable Interrupt Controller (PIC)
+ *	Register Interface Specification Revision 1.2
+ *
+ *	Issue Date: October 1995
+ *
+ *	Issued jointly by Advanced Micro Devices and Cyrix Corporation
+ *
+ *	AMD is a registered trademark of Advanced Micro Devices, Inc.
+ *	Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc.
+ *	All Rights Reserved.
+ *
+ *  To receive a copy of this documentation, send an email to openpic@amd.com.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#ifndef _LINUX_OPENPIC_H
+#define _LINUX_OPENPIC_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+    /*
+     *  OpenPIC supports up to 2048 interrupt sources and up to 32 processors
+     */
+
+#define OPENPIC_MAX_SOURCES	2048
+#define OPENPIC_MAX_PROCESSORS	32
+#define OPENPIC_MAX_ISU		16
+
+#define OPENPIC_NUM_TIMERS	4
+#define OPENPIC_NUM_IPI		4
+#define OPENPIC_NUM_PRI		16
+#define OPENPIC_NUM_VECTORS	256
+
+
+    /*
+     *  Non-offset'ed vector numbers
+     */
+
+#define OPENPIC_VEC_TIMER       64    /* and up */
+#define OPENPIC_VEC_IPI         72    /* and up */
+#define OPENPIC_VEC_SPURIOUS    127
+
+
+    /*
+     *  OpenPIC Registers are 32 bits and aligned on 128 bit boundaries
+     */
+
+typedef struct _OpenPIC_Reg {
+    u_int Reg;					/* Little endian! */
+    char Pad[0xc];
+} OpenPIC_Reg;
+
+
+    /*
+     *  Per Processor Registers
+     */
+
+typedef struct _OpenPIC_Processor {
+    /*
+     *  Private Shadow Registers (for SLiC backwards compatibility)
+     */
+    u_int IPI0_Dispatch_Shadow;			/* Write Only */
+    char Pad1[0x4];
+    u_int IPI0_Vector_Priority_Shadow;		/* Read/Write */
+    char Pad2[0x34];
+    /*
+     *  Interprocessor Interrupt Command Ports
+     */
+    OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI];	/* Write Only */
+    /*
+     *  Current Task Priority Register
+     */
+    OpenPIC_Reg _Current_Task_Priority;		/* Read/Write */
+    char Pad3[0x10];
+    /*
+     *  Interrupt Acknowledge Register
+     */
+    OpenPIC_Reg _Interrupt_Acknowledge;		/* Read Only */
+    /*
+     *  End of Interrupt (EOI) Register
+     */
+    OpenPIC_Reg _EOI;				/* Read/Write */
+    char Pad5[0xf40];
+} OpenPIC_Processor;
+
+
+    /*
+     *  Timer Registers
+     */
+
+typedef struct _OpenPIC_Timer {
+    OpenPIC_Reg _Current_Count;			/* Read Only */
+    OpenPIC_Reg _Base_Count;			/* Read/Write */
+    OpenPIC_Reg _Vector_Priority;		/* Read/Write */
+    OpenPIC_Reg _Destination;			/* Read/Write */
+} OpenPIC_Timer;
+
+
+    /*
+     *  Global Registers
+     */
+
+typedef struct _OpenPIC_Global {
+    /*
+     *  Feature Reporting Registers
+     */
+    OpenPIC_Reg _Feature_Reporting0;		/* Read Only */
+    OpenPIC_Reg _Feature_Reporting1;		/* Future Expansion */
+    /*
+     *  Global Configuration Registers
+     */
+    OpenPIC_Reg _Global_Configuration0;		/* Read/Write */
+    OpenPIC_Reg _Global_Configuration1;		/* Future Expansion */
+    /*
+     *  Vendor Specific Registers
+     */
+    OpenPIC_Reg _Vendor_Specific[4];
+    /*
+     *  Vendor Identification Register
+     */
+    OpenPIC_Reg _Vendor_Identification;		/* Read Only */
+    /*
+     *  Processor Initialization Register
+     */
+    OpenPIC_Reg _Processor_Initialization;	/* Read/Write */
+    /*
+     *  IPI Vector/Priority Registers
+     */
+    OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI];	/* Read/Write */
+    /*
+     *  Spurious Vector Register
+     */
+    OpenPIC_Reg _Spurious_Vector;		/* Read/Write */
+    /*
+     *  Global Timer Registers
+     */
+    OpenPIC_Reg _Timer_Frequency;		/* Read/Write */
+    OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS];
+    char Pad1[0xee00];
+} OpenPIC_Global;
+
+
+    /*
+     *  Interrupt Source Registers
+     */
+
+typedef struct _OpenPIC_Source {
+    OpenPIC_Reg _Vector_Priority;		/* Read/Write */
+    OpenPIC_Reg _Destination;			/* Read/Write */
+} OpenPIC_Source, *OpenPIC_SourcePtr;
+
+
+    /*
+     *  OpenPIC Register Map
+     */
+
+struct OpenPIC {
+    char Pad1[0x1000];
+    /*
+     *  Global Registers
+     */
+    OpenPIC_Global Global;
+    /*
+     *  Interrupt Source Configuration Registers
+     */
+    OpenPIC_Source Source[OPENPIC_MAX_SOURCES];
+    /*
+     *  Per Processor Registers
+     */
+    OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
+};
+
+extern volatile struct OpenPIC *OpenPIC;
+
+
+    /*
+     *  Current Task Priority Register
+     */
+
+#define OPENPIC_CURRENT_TASK_PRIORITY_MASK	0x0000000f
+
+    /*
+     *  Who Am I Register
+     */
+
+#define OPENPIC_WHO_AM_I_ID_MASK		0x0000001f
+
+    /*
+     *  Feature Reporting Register 0
+     */
+
+#define OPENPIC_FEATURE_LAST_SOURCE_MASK	0x07ff0000
+#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT	16
+#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK	0x00001f00
+#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT	8
+#define OPENPIC_FEATURE_VERSION_MASK		0x000000ff
+
+    /*
+     *  Global Configuration Register 0
+     */
+
+#define OPENPIC_CONFIG_RESET			0x80000000
+#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE	0x20000000
+#define OPENPIC_CONFIG_BASE_MASK		0x000fffff
+
+    /*
+     *  Vendor Identification Register
+     */
+
+#define OPENPIC_VENDOR_ID_STEPPING_MASK		0x00ff0000
+#define OPENPIC_VENDOR_ID_STEPPING_SHIFT	16
+#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK	0x0000ff00
+#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT	8
+#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK	0x000000ff
+
+    /*
+     *  Vector/Priority Registers
+     */
+
+#define OPENPIC_MASK				0x80000000
+#define OPENPIC_ACTIVITY			0x40000000	/* Read Only */
+#define OPENPIC_PRIORITY_MASK			0x000f0000
+#define OPENPIC_PRIORITY_SHIFT			16
+#define OPENPIC_VECTOR_MASK			0x000000ff
+
+
+    /*
+     *  Interrupt Source Registers
+     */
+
+#define OPENPIC_POLARITY_POSITIVE		0x00800000
+#define OPENPIC_POLARITY_NEGATIVE		0x00000000
+#define OPENPIC_POLARITY_MASK			0x00800000
+#define OPENPIC_SENSE_LEVEL			0x00400000
+#define OPENPIC_SENSE_EDGE			0x00000000
+#define OPENPIC_SENSE_MASK			0x00400000
+
+
+    /*
+     *  Timer Registers
+     */
+
+#define OPENPIC_COUNT_MASK			0x7fffffff
+#define OPENPIC_TIMER_TOGGLE			0x80000000
+#define OPENPIC_TIMER_COUNT_INHIBIT		0x80000000
+
+
+    /*
+     *  Aliases to make life simpler
+     */
+
+/* Per Processor Registers */
+#define IPI_Dispatch(i)			_IPI_Dispatch[i].Reg
+#define Current_Task_Priority		_Current_Task_Priority.Reg
+#define Interrupt_Acknowledge		_Interrupt_Acknowledge.Reg
+#define EOI				_EOI.Reg
+
+/* Global Registers */
+#define Feature_Reporting0		_Feature_Reporting0.Reg
+#define Feature_Reporting1		_Feature_Reporting1.Reg
+#define Global_Configuration0		_Global_Configuration0.Reg
+#define Global_Configuration1		_Global_Configuration1.Reg
+#define Vendor_Specific(i)		_Vendor_Specific[i].Reg
+#define Vendor_Identification		_Vendor_Identification.Reg
+#define Processor_Initialization	_Processor_Initialization.Reg
+#define IPI_Vector_Priority(i)		_IPI_Vector_Priority[i].Reg
+#define Spurious_Vector			_Spurious_Vector.Reg
+#define Timer_Frequency			_Timer_Frequency.Reg
+
+/* Timer Registers */
+#define Current_Count			_Current_Count.Reg
+#define Base_Count			_Base_Count.Reg
+#define Vector_Priority			_Vector_Priority.Reg
+#define Destination			_Destination.Reg
+
+/* Interrupt Source Registers */
+#define Vector_Priority			_Vector_Priority.Reg
+#define Destination			_Destination.Reg
+
+    /*
+     *  Local (static) OpenPIC Operations
+     */
+
+
+/* Global Operations */
+static void openpic_reset(void);
+static void openpic_enable_8259_pass_through(void);
+static void openpic_disable_8259_pass_through(void);
+static u_int openpic_irq(void);
+static void openpic_eoi(void);
+static u_int openpic_get_priority(void);
+static void openpic_set_priority(u_int pri);
+static u_int openpic_get_spurious(void);
+static void openpic_set_spurious(u_int vector);
+
+#ifdef CONFIG_SMP
+/* Interprocessor Interrupts */
+static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
+static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
+#endif
+
+/* Timer Interrupts */
+static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
+static void openpic_maptimer(u_int timer, u_int cpumask);
+
+/* Interrupt Sources */
+static void openpic_enable_irq(u_int irq);
+static void openpic_disable_irq(u_int irq);
+static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
+			    int is_level);
+static void openpic_mapirq(u_int irq, u_int cpumask);
+static void openpic_set_sense(u_int irq, int sense);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_OPENPIC_H */
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.4.0/linux/arch/ppc/kernel/pci.c	Tue Nov  7 11:25:00 2000
+++ linux/arch/ppc/kernel/pci.c	Wed Jan 24 15:28:36 2001
@@ -3,15 +3,16 @@
  * Common pmac/prep/chrp pci routines. -- Cort
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/openpic.h>
 #include <linux/capability.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/bootmem.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -25,7 +26,7 @@
 
 #include "pci.h"
 
-#undef DEBUG
+#define DEBUG
 
 #ifdef DEBUG
 #define DBG(x...) printk(x)
@@ -37,54 +38,44 @@
 unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
 
-struct pci_fixup pcibios_fixups[] = {
-	{ 0 }
-};
+static u8* pci_to_OF_bus_map;
 
-int generic_pcibios_read_byte(struct pci_dev *dev, int where, u8 *val)
-{
-	return ppc_md.pcibios_read_config_byte(dev->bus->number,dev->devfn,where,val);
-}
-int generic_pcibios_read_word(struct pci_dev *dev, int where, u16 *val)
-{
-	return ppc_md.pcibios_read_config_word(dev->bus->number,dev->devfn,where,val);
-}
-int generic_pcibios_read_dword(struct pci_dev *dev, int where, u32 *val)
-{
-	return ppc_md.pcibios_read_config_dword(dev->bus->number,dev->devfn,where,val);
-}
-int generic_pcibios_write_byte(struct pci_dev *dev, int where, u8 val)
-{
-	return ppc_md.pcibios_write_config_byte(dev->bus->number,dev->devfn,where,val);
-}
-int generic_pcibios_write_word(struct pci_dev *dev, int where, u16 val)
-{
-	return ppc_md.pcibios_write_config_word(dev->bus->number,dev->devfn,where,val);
-}
-int generic_pcibios_write_dword(struct pci_dev *dev, int where, u32 val)
-{
-	return ppc_md.pcibios_write_config_dword(dev->bus->number,dev->devfn,where,val);
-}
+static void pcibios_fixup_resources(struct pci_dev* dev);
+#ifdef CONFIG_ALL_PPC
+static void pcibios_fixup_cardbus(struct pci_dev* dev);
+#endif
 
-struct pci_ops generic_pci_ops = 
-{
-	generic_pcibios_read_byte,
-	generic_pcibios_read_word,
-	generic_pcibios_read_dword,
-	generic_pcibios_write_byte,
-	generic_pcibios_write_word,
-	generic_pcibios_write_dword
-};
+/* By default, we don't re-assign bus numbers. We do this only on
+ * some pmacs
+ */
+int pci_assign_all_busses;
 
+struct pci_controller* hose_head;
+struct pci_controller** hose_tail = &hose_head;
 
+static int pci_bus_count;
 
-void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+struct pci_fixup pcibios_fixups[] = {
+	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,		PCI_ANY_ID,		pcibios_fixup_resources },
+#ifdef CONFIG_ALL_PPC
+	/* We should add per-machine fixup support in xxx_setup.c or xxx_pci.c */
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_TI, 	PCI_DEVICE_ID_TI_1211, 	pcibios_fixup_cardbus }, 
+#endif /* CONFIG_ALL_PPC */
+ 	{ 0 }
+};
+
+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);
+	struct pci_controller* hose = dev->sysdata;
+	
+	new = res->start;
+	if (hose && res->flags & IORESOURCE_MEM)
+		new -= hose->pci_mem_offset;
+	new |= (res->flags & PCI_REGION_FLAG_MASK);
 	if (resource < 6) {
 		reg = PCI_BASE_ADDRESS_0 + 4*resource;
 	} else if (resource == PCI_ROM_RESOURCE) {
@@ -104,6 +95,62 @@
 	}
 }
 
+static void
+pcibios_fixup_resources(struct pci_dev* dev)
+{
+	struct pci_controller* hose =
+		(struct pci_controller *)dev->sysdata;
+	int i;
+	if (!hose) {
+		printk("No hose for PCI dev %x.%x !\n", dev->bus->number, dev->devfn >> 3);
+		return;
+	}
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		struct resource *res = dev->resource + i;
+		if (!res->start)
+			continue;
+		if (res->flags & IORESOURCE_MEM) {
+			res->start += hose->pci_mem_offset;
+			res->end += hose->pci_mem_offset;
+#ifdef DEBUG
+			printk("Fixup mem res, dev: %x.%x, res_start: %lx->%lx\n",
+			       dev->bus->number, dev->devfn>>3, res->start-hose->pci_mem_offset,
+			       res->start);
+#endif
+		}
+
+		if ((res->flags & IORESOURCE_IO)
+		    && (unsigned long) hose->io_base_virt != isa_io_base) {
+			unsigned long offs = (unsigned long) hose->io_base_virt - isa_io_base;
+			res->start += offs;
+			res->end += offs;
+			printk("Fixup IO res, dev: %x.%x, res_start: %lx->%lx\n",
+			       dev->bus->number, dev->devfn>>3,
+			       res->start - offs, res->start);
+		}
+	}
+}
+
+#ifdef CONFIG_ALL_PPC
+static void
+pcibios_fixup_cardbus(struct pci_dev* dev)
+{
+	/*
+	 * Fix the interrupt routing on the TI1211 chip on the 1999
+	 * G3 powerbook, which doesn't get initialized properly by OF.
+	 */
+	if (dev->vendor == PCI_VENDOR_ID_TI
+	    && dev->device == PCI_DEVICE_ID_TI_1211) {
+		u32 val;
+		/* 0x8c == TI122X_IRQMUX, 2 says to route the INTA
+		   signal out the MFUNC0 pin */
+		if (pci_read_config_dword(dev, 0x8c, &val) == 0
+		    && val == 0)
+			pci_write_config_dword(dev, 0x8c, 2);
+	}
+}
+#endif /* CONFIG_ALL_PPC */
+
 /*
  * We need to avoid collisions with `mirrored' VGA ports
  * and other strange ISA hardware, so we always want the
@@ -172,7 +219,8 @@
  *	    as well.
  */
 
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+static void __init
+pcibios_allocate_bus_resources(struct list_head *bus_list)
 {
 	struct list_head *ln;
 	struct pci_bus *bus;
@@ -197,7 +245,8 @@
 	}
 }
 
-static void __init pcibios_allocate_resources(int pass)
+static void __init
+pcibios_allocate_resources(int pass)
 {
 	struct pci_dev *dev;
 	int idx, disabled;
@@ -250,7 +299,8 @@
 	}
 }
 
-static void __init pcibios_assign_resources(void)
+static void __init
+pcibios_assign_resources(void)
 {
 	struct pci_dev *dev;
 	int idx;
@@ -278,7 +328,9 @@
 			 *  the BIOS forgot to do so or because we have decided the old
 			 *  address was unusable for some reason.
 			 */
-			if (!r->start && r->end)
+			if (!r->start && r->end &&
+			    (!ppc_md.pcibios_enable_device_hook ||
+			     !ppc_md.pcibios_enable_device_hook(dev, 1)))
 				pci_assign_resource(dev, idx);
 		}
 
@@ -293,7 +345,8 @@
 }
 
 
-int pcibios_enable_resources(struct pci_dev *dev)
+int
+pcibios_enable_resources(struct pci_dev *dev)
 {
 	u16 cmd, old_cmd;
 	int idx;
@@ -321,18 +374,267 @@
 	return 0;
 }
 
+struct pci_controller * __init
+pcibios_alloc_controller(void)
+{
+	struct pci_controller *hose;
+
+	hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));
+	memset(hose, 0, sizeof(struct pci_controller));
+	
+	*hose_tail = hose;
+	hose_tail = &hose->next;
+
+	return hose;
+}
+
+static void
+make_one_node_map(struct device_node* node, u8 pci_bus)
+{
+	int *bus_range;
+	int len;
+	
+	if (pci_bus >= pci_bus_count)
+		return;
+	bus_range = (int *) get_property(node, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING "Can't get bus-range for %s\n",
+			       node->full_name);
+		return;
+	}
+	pci_to_OF_bus_map[pci_bus] = bus_range[0];
+	
+	for (node=node->child; node != 0;node = node->sibling) {
+		struct pci_dev* dev;
+		unsigned int *class_code, *reg;
+		
+		class_code = (unsigned int *) get_property(node, "class-code", 0);
+		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+			continue;
+		reg = (unsigned int *)get_property(node, "reg", 0);
+		if (!reg)
+			continue;
+		dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
+		if (!dev || !dev->subordinate)
+			continue;
+		make_one_node_map(node, dev->subordinate->number);
+	}
+}
+		
+void
+pcibios_make_OF_bus_map(void)
+{
+	int i;
+	struct pci_controller* hose;
+	u8* of_prop_map;
+	
+	pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
+	if (!pci_to_OF_bus_map) {
+		printk(KERN_ERR "Can't allocate OF bus map !\n");
+		return;
+	}
+	
+	/* We fill the bus map with invalid values, that helps
+	 * debugging.
+	 */
+	for (i=0; i<pci_bus_count; i++)
+		pci_to_OF_bus_map[i] = 0xff;
+	
+	/* For each hose, we begin searching bridges */
+	for(hose=hose_head; hose; hose=hose->next) {
+		struct device_node* node;		
+		node = (struct device_node *)hose->arch_data;
+		if (!node)
+			continue;
+		make_one_node_map(node, hose->first_busno);
+	}
+	of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", 0);
+	if (of_prop_map)
+		memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);
+#ifdef DEBUG
+	printk("PCI->OF bus map:\n");
+	for (i=0; i<pci_bus_count; i++) {
+		if (pci_to_OF_bus_map[i] == 0xff)
+			continue;
+		printk("%d -> %d\n", i, pci_to_OF_bus_map[i]);
+	}
+#endif	
+}
+
+static struct device_node*
+scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
+{
+	struct device_node* sub_node;
+	
+	for (; node != 0;node = node->sibling) {
+		unsigned int *class_code, *reg;
+		
+		reg = (unsigned int *) get_property(node, "reg", 0);
+		if (reg && ((reg[0] >> 8) & 0xff) == dev_fn
+			&& ((reg[0] >> 16) & 0xff) == bus)
+			return node;
+
+		/* For PCI<->PCI bridges or CardBus bridges, we go down */
+		class_code = (unsigned int *) get_property(node, "class-code", 0);
+		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+			continue;
+		sub_node = scan_OF_childs_for_device(node->child, bus, dev_fn);
+		if (sub_node)
+			return sub_node;
+	}
+	return NULL;
+}
 
+/* 
+ * Scans the OF tree for a device node matching a PCI device
+ */
+struct device_node*
+pci_device_to_OF_node(struct pci_dev *dev)
+{
+	struct pci_controller *hose;
+	struct device_node *node;
+	int bus;
+	
+	if (!have_of)
+		return NULL;
+		
+	/* Lookup the hose */
+	bus = dev->bus->number;
+	hose = pci_bus_to_hose(bus);
+	if (!hose)
+		return NULL;
+
+	/* Check it has an OF node associated */
+	node = (struct device_node *) hose->arch_data;
+	if (!node)
+		return NULL;
+
+	/* Fixup bus number according to what OF think it is. */
+	if (pci_to_OF_bus_map)
+		bus = pci_to_OF_bus_map[bus];
+	if (bus == 0xff)
+		return NULL;
+		
+	/* Now, lookup childs of the hose */
+	return scan_OF_childs_for_device(node->child, bus, dev->devfn);
+}
+
+/* This routine is meant to be used early during boot, when the
+ * PCI bus numbers have not yet been assigned, and you need to
+ * issue PCI config cycles to an OF device.
+ * It could also be used to "fix" RTAS config cycles if you want
+ * to set pci_assign_all_busses to 1 and still use RTAS for PCI
+ * config cycles.
+ */
+struct pci_controller*
+pci_find_hose_for_OF_device(struct device_node* node)
+{
+	if (!have_of)
+		return NULL;
+	while(node) {
+		struct pci_controller* hose;
+		for (hose=hose_head;hose;hose=hose->next)
+			if (hose->arch_data == node)
+				return hose;
+		node=node->parent;
+	}
+	return NULL;
+}
+
+/* 
+ * Returns the PCI device matching a given OF node
+ */
+int
+pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
+{
+	unsigned int *reg;
+	int i;
+		
+	if (!have_of)
+		return -ENODEV;
+	reg = (unsigned int *) get_property(node, "reg", 0);
+	if (!reg)
+		return -ENODEV;
+	*bus = (reg[0] >> 16) & 0xff;
+	for (i=0; pci_to_OF_bus_map && i<pci_bus_count; i++)
+		if (pci_to_OF_bus_map[i] == *bus) {
+			*bus = i;
+			break;
+		}
+	*devfn = ((reg[0] >> 8) & 0xff);
+	return 0;
+}
 
-void __init pcibios_init(void)
+void __init
+pcibios_init(void)
 {
+	struct pci_controller *hose;
+	struct pci_bus *bus;
+	int next_busno;
+
 	printk("PCI: Probing PCI hardware\n");
-	pci_scan_bus(0, &generic_pci_ops, NULL);
+
+	/* Scan all of the recorded PCI controllers.  */
+	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+		if (pci_assign_all_busses)
+			hose->first_busno = next_busno;
+		hose->last_busno = 0xff;
+		bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
+		hose->bus = bus;
+		hose->last_busno = bus->subordinate;
+		if (pci_assign_all_busses || next_busno <= hose->last_busno)
+			next_busno = hose->last_busno+1;
+	}
+	pci_bus_count = next_busno;
+
+	/* OpenFirmware based machines need a map of OF bus
+	 * numbers vs. kernel bus numbers since we may have to
+	 * remap them.
+	 */
+	if (pci_assign_all_busses && have_of)
+		pcibios_make_OF_bus_map();
+		
+	/* Call machine dependant fixup */
 	if (ppc_md.pcibios_fixup)
 		ppc_md.pcibios_fixup();
+
+	/* Allocate and assign resources */
 	pcibios_allocate_bus_resources(&pci_root_buses);
 	pcibios_allocate_resources(0);
 	pcibios_allocate_resources(1);
 	pcibios_assign_resources();
+
+#ifdef CONFIG_BLK_DEV_IDE
+	/* OF fails to initialize IDE controllers on macs
+	 * (and maybe other machines)
+	 * 
+	 * This late fixup is done here since I want it to happen after
+	 * resource assignement, and there's no "late-init" arch hook
+	 * 
+	 * Ideally, this should be moved to the IDE layer, but we need
+	 * to check specifically with Andre Hedrick how to do it cleanly
+	 * since the common IDE code seem to care about the fact that the
+	 * BIOS may have disabled a controller.
+	 * 
+	 * -- BenH
+	 */
+	if (_machine == _MACH_Pmac) {
+		struct pci_dev *dev;
+		pci_for_each_dev(dev)
+		{
+			if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
+				pci_enable_device(dev);
+		}
+	}
+#endif /* CONFIG_BLK_DEV_IDE */
+}
+
+int __init
+pcibios_assign_all_busses(void)
+{
+	return pci_assign_all_busses;
 }
 
 void __init
@@ -344,9 +646,16 @@
 	ranges->mem_end -= bus->resource[1]->start;
 }
 
+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
+			     unsigned long start, unsigned long size)
+{
+	return start;
+}
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
+	pci_read_bridge_bases(bus);
+	
 	if ( ppc_md.pcibios_fixup_bus )
 		ppc_md.pcibios_fixup_bus(bus);
 }
@@ -370,6 +679,10 @@
 	int idx;
 	struct resource *r;
 
+	if (ppc_md.pcibios_enable_device_hook)
+		if (ppc_md.pcibios_enable_device_hook(dev, 0))
+			return -EINVAL;
+			
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	old_cmd = cmd;
 	for (idx=0; idx<6; idx++) {
@@ -391,37 +704,99 @@
 	return 0;
 }
 
-void *
-pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical)
+struct pci_controller*
+pci_bus_to_hose(int bus)
 {
-	if (!ppc_md.pci_dev_io_base) {
-		/* Please, someone fix this for non-pmac machines, we
-		 * need either the virtual or physical PCI IO base
-		 */
-		return 0;
-	}
-	return ppc_md.pci_dev_io_base(bus, devfn, physical);
+	struct pci_controller* hose = hose_head;
+
+	for (; hose; hose = hose->next)
+		if (bus >= hose->first_busno && bus <= hose->last_busno)
+			return hose;
+	return NULL;
 }
 
-void *
-pci_dev_mem_base(unsigned char bus, unsigned char devfn)
+void*
+pci_bus_io_base(unsigned int bus)
 {
-	/* Default memory base is 0 (1:1 mapping) */
-	if (!ppc_md.pci_dev_mem_base) {
-		/* Please, someone fix this for non-pmac machines.*/
+	struct pci_controller *hose;
+
+	hose = pci_bus_to_hose(bus);
+	if (!hose)
+		return NULL;
+	return hose->io_base_virt;
+}
+
+unsigned long
+pci_bus_io_base_phys(unsigned int bus)
+{
+	struct pci_controller *hose;
+
+	hose = pci_bus_to_hose(bus);
+	if (!hose)
 		return 0;
-	}
-	return ppc_md.pci_dev_mem_base(bus, devfn);
+	return hose->io_base_phys;
 }
 
-/* Returns the root-bridge number (Uni-N number) of a device */
-int
-pci_dev_root_bridge(unsigned char bus, unsigned char devfn)
+unsigned long
+pci_bus_mem_base_phys(unsigned int bus)
 {
-	/* Defaults to 0 */
-	if (!ppc_md.pci_dev_root_bridge)
+	struct pci_controller *hose;
+
+	hose = pci_bus_to_hose(bus);
+	if (!hose)
 		return 0;
-	return ppc_md.pci_dev_root_bridge(bus, devfn);
+	return hose->pci_mem_offset;
+}
+
+#ifdef CONFIG_POWER4
+extern unsigned long pci_address_offset(int, unsigned int);
+#endif /* CONFIG_POWER4 */
+
+unsigned long
+pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
+{
+	/* Hack alert again ! See comments in chrp_pci.c
+	 */
+#ifdef CONFIG_POWER4
+	unsigned long offset = pci_address_offset(pdev->bus->number, res->flags);
+	return res->start - offset;
+#else /* CONFIG_POWER4 */
+	struct pci_controller* hose =
+		(struct pci_controller *)pdev->sysdata;
+	if (hose && res->flags & IORESOURCE_MEM)
+		return res->start - hose->pci_mem_offset;
+	/* We may want to do something with IOs here... */
+	return res->start;
+#endif	
+}
+
+/* Obsolete functions. Should be removed once the symbios driver
+ * is fixed
+ */
+unsigned long
+pci_phys_to_bus(unsigned long pa, int busnr)
+{
+#ifdef CONFIG_POWER4
+	return pa - pci_address_offset(busnr, IORESOURCE_MEM);
+#else /* CONFIG_POWER4 */
+	struct pci_controller* hose = pci_bus_to_hose(busnr);
+	if (!hose)
+		return pa;
+	return pa - hose->pci_mem_offset;
+#endif
+}
+
+unsigned long
+pci_bus_to_phys(unsigned int ba, int busnr)
+{
+#ifdef CONFIG_POWER4
+	return ba + pci_address_offset(dev->bus->number, IORESOURCE_MEM);
+#else /* CONFIG_POWER4 */
+	struct pci_controller* hose = pci_bus_to_hose(busnr);
+	if (!hose)
+		return ba;
+	return ba + hose->pci_mem_offset;
+#endif
 }
 
 /* Provide information on locations of various I/O regions in physical
@@ -430,23 +805,93 @@
  * Note that the returned IO or memory base is a physical address
  */
 
-asmlinkage long
+long
 sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
 {
+	struct pci_controller* hose = pci_bus_to_hose(bus);
 	long result = -EOPNOTSUPP;
+
+	if (!hose)
+		return -ENODEV;
 	
 	switch (which) {
 	case IOBASE_BRIDGE_NUMBER:
-		return (long)pci_dev_root_bridge(bus, devfn);
+		return (long)hose->first_busno;
 	case IOBASE_MEMORY:
-		return (long)pci_dev_mem_base(bus, devfn);
+		return (long)hose->pci_mem_offset;
 	case IOBASE_IO:
-		result = (long)pci_dev_io_base(bus, devfn, 1);
-		if (result == 0)
-			result = -EOPNOTSUPP;
-		break;
+		return (long)hose->io_base_phys;
+	case IOBASE_ISA_IO:
+		return (long)isa_io_base;
+	case IOBASE_ISA_MEM:
+		return (long)isa_mem_base;
 	}
 
 	return result;
 }
 
+/*
+ * Null PCI config access functions, for the case when we can't
+ * find a hose.
+ */
+#define NULL_PCI_OP(rw, size, type)					\
+static int								\
+null_##rw##_config_##size(struct pci_dev *dev, int offset, type val)	\
+{									\
+	return PCIBIOS_DEVICE_NOT_FOUND;    				\
+}
+
+NULL_PCI_OP(read, byte, u8 *)
+NULL_PCI_OP(read, word, u16 *)
+NULL_PCI_OP(read, dword, u32 *)
+NULL_PCI_OP(write, byte, u8)
+NULL_PCI_OP(write, word, u16)
+NULL_PCI_OP(write, dword, u32)
+
+static struct pci_ops null_pci_ops =
+{
+	null_read_config_byte,
+	null_read_config_word,
+	null_read_config_dword,
+	null_write_config_byte,
+	null_write_config_word,
+	null_write_config_dword
+};
+
+/*
+ * These functions are used early on before PCI scanning is done
+ * and all of the pci_dev and pci_bus structures have been created.
+ */
+static struct pci_dev *
+fake_pci_dev(struct pci_controller *hose, int busnr, int devfn)
+{
+	static struct pci_dev dev;
+	static struct pci_bus bus;
+
+	if (hose == 0) {
+		hose = pci_bus_to_hose(busnr);
+		if (hose == 0)
+			printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);
+	}
+	dev.bus = &bus;
+	dev.sysdata = hose;
+	dev.devfn = devfn;
+	bus.number = busnr;
+	bus.ops = hose? hose->ops: &null_pci_ops;
+	return &dev;
+}
+
+#define EARLY_PCI_OP(rw, size, type)					\
+int early_##rw##_config_##size(struct pci_controller *hose, int bus,	\
+			       int devfn, int offset, type value)	\
+{									\
+	return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn),	\
+					offset, value);			\
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/pci.h linux/arch/ppc/kernel/pci.h
--- v2.4.0/linux/arch/ppc/kernel/pci.h	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/kernel/pci.h	Mon Jan 22 15:41:15 2001
@@ -2,47 +2,23 @@
 #ifndef __PPC_KERNEL_PCI_H__
 #define __PPC_KERNEL_PCI_H__
 
+/* Configure those in your xxx_init() or xxx_setup_arch() function */
 extern unsigned long isa_io_base;
 extern unsigned long isa_mem_base;
 extern unsigned long pci_dram_offset;
 
-extern unsigned int  *pci_config_address;
-extern unsigned char *pci_config_data;
+/* Set this to 1 if you want the kernel to re-assign all PCI
+ * bus numbers
+ */
+extern int pci_assign_all_busses;
 
-void fix_intr(struct device_node *node, struct pci_dev *dev);
 
-#if 0
-#define decl_config_access_method(name) 	\
-struct pci_ops name##_pci_ops = { 		\
-	name##_pcibios_read_config_byte,	\
-	name##_pcibios_read_config_word,	\
-	name##_pcibios_read_config_dword,	\
-	name##_pcibios_write_config_byte,	\
-	name##_pcibios_write_config_word,	\
-	name##_pcibios_write_config_dword	\
-}
-#endif
+extern struct pci_controller* pcibios_alloc_controller(void);
+extern struct pci_controller* pci_find_hose_for_OF_device(
+			struct device_node* node);
 
-#define decl_config_access_method(name) \
-extern int name##_pcibios_read_config_byte(unsigned char bus, \
-	unsigned char dev_fn, unsigned char offset, unsigned char *val); \
-extern int name##_pcibios_read_config_word(unsigned char bus, \
-	unsigned char dev_fn, unsigned char offset, unsigned short *val); \
-extern int name##_pcibios_read_config_dword(unsigned char bus, \
-	unsigned char dev_fn, unsigned char offset, unsigned int *val); \
-extern int name##_pcibios_write_config_byte(unsigned char bus, \
-	unsigned char dev_fn, unsigned char offset, unsigned char val); \
-extern int name##_pcibios_write_config_word(unsigned char bus, \
-	unsigned char dev_fn, unsigned char offset, unsigned short val); \
-extern int name##_pcibios_write_config_dword(unsigned char bus, \
-	unsigned char dev_fn, unsigned char offset, unsigned int val)
-
-#define set_config_access_method(name) \
-	ppc_md.pcibios_read_config_byte = name##_pcibios_read_config_byte; \
-	ppc_md.pcibios_read_config_word = name##_pcibios_read_config_word; \
-	ppc_md.pcibios_read_config_dword = name##_pcibios_read_config_dword; \
-	ppc_md.pcibios_write_config_byte = name##_pcibios_write_config_byte; \
-	ppc_md.pcibios_write_config_word = name##_pcibios_write_config_word; \
-	ppc_md.pcibios_write_config_dword = name##_pcibios_write_config_dword
+extern void setup_indirect_pci(struct pci_controller* hose,
+			u32 cfg_addr, u32 cfg_data);
+extern void setup_grackle(struct pci_controller *hose, unsigned io_space_size);
 
 #endif /* __PPC_KERNEL_PCI_H__ */
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- v2.4.0/linux/arch/ppc/kernel/pmac_pci.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/pmac_pci.c	Mon Jan 22 15:41:15 2001
@@ -27,23 +27,14 @@
 
 #include "pci.h"
 
-struct bridge_data **bridges, *bridge_list;
-static int max_bus;
-
-struct uninorth_data {
-	struct device_node*	node;
-	volatile unsigned int*	cfg_addr;
-	volatile unsigned int*	cfg_data;
-	void*			iobase;
-	unsigned long		iobase_phys;
-};
-
-static struct uninorth_data uninorth_bridges[3];
-static int uninorth_count;
-static int uninorth_default = -1;
+#undef DEBUG
 
 static void add_bridges(struct device_node *dev);
 
+/* XXX Could be per-controller, but I don't think we risk anything by
+ * assuming we won't have both UniNorth and Bandit */
+static int has_uninorth;
+
 /*
  * Magic constants for enabling cache coherency in the bandit/PSX bridge.
  */
@@ -56,477 +47,201 @@
 #define BANDIT_MAGIC	0x50
 #define BANDIT_COHERENT	0x40
 
-/* Obsolete, should be replaced by pmac_pci_dev_io_base() (below) */
-__pmac
-void *pci_io_base(unsigned int bus)
+static int __init
+fixup_one_level_bus_range(struct device_node *node, int higher)
 {
-	struct bridge_data *bp;
-
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return 0;
-	return bp->io_base;
-}
-
-__pmac
-int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
-		   unsigned char *devfn_ptr)
-{
-	unsigned int *reg;
-	int len;
+	for (; node != 0;node = node->sibling) {
+		int * bus_range;
+		unsigned int *class_code;			
+		int len;
 
-	reg = (unsigned int *) get_property(dev, "reg", &len);
-	if (reg == 0 || len < 5 * sizeof(unsigned int)) {
-		/* doesn't look like a PCI device */
-		*bus_ptr = 0xff;
-		*devfn_ptr = 0xff;
-		return -1;
+		/* For PCI<->PCI bridges or CardBus bridges, we go down */
+		class_code = (unsigned int *) get_property(node, "class-code", 0);
+		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+			continue;
+		bus_range = (int *) get_property(node, "bus-range", &len);
+		if (bus_range != NULL && len > 2 * sizeof(int)) {
+			if (bus_range[1] > higher)
+				higher = bus_range[1];
+		}
+		higher = fixup_one_level_bus_range(node->child, higher);
 	}
-	*bus_ptr = reg[0] >> 16;
-	*devfn_ptr = reg[0] >> 8;
-	return 0;
+	return higher;
 }
 
-/* This routines figures out on which root bridge a given PCI device
- * is attached.
+/* This routine fixes the "bus-range" property of all bridges in the
+ * system since they tend to have their "last" member wrong on macs
+ * 
+ * Note that the bus numbers manipulated here are OF bus numbers, they
+ * are not Linux bus numbers.
  */
-__pmac
-int
-pmac_pci_dev_root_bridge(unsigned char bus, unsigned char dev_fn)
+static void __init
+fixup_bus_range(struct device_node *bridge)
 {
-	struct device_node *node, *bridge_node;
-	int bridge = uninorth_default;
-
-	if (uninorth_count == 0)
-		return 0;
-	if (bus == 0 && PCI_SLOT(dev_fn) < 11)
-		return 0;
+	int * bus_range;
+	int len;
 	
-	/* We look for the OF device corresponding to this bus/devfn pair. If we
-	 * don't find it, we default to the external PCI */
-	bridge_node = NULL;
-	node = find_pci_device_OFnode(bus, dev_fn & 0xf8);
-	if (node) {
-	    /* note: we don't stop on the first occurence since we need to go
-             * up to the root bridge */
-	    do {
-		if (node->type && !strcmp(node->type, "pci") 
-			&& device_is_compatible(node, "uni-north"))
-			bridge_node = node;
-		node=node->parent;
-	    } while (node);
-	}
-	if (bridge_node) {
-	    int i;
-	    for (i=0;i<uninorth_count;i++)
-		if (uninorth_bridges[i].node == bridge_node) {
-		    bridge = i;
-		    break;
-		}
-	}
-
-	if (bridge == -1) {
-		printk(KERN_WARNING "pmac_pci: no default bridge !\n");
-		return 0;
-	}
-
-	return bridge;	
-}
-
-__pmac
-void *
-pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical)
-{
-	int bridge = -1;
-	if (uninorth_count != 0)
-		bridge = pmac_pci_dev_root_bridge(bus, devfn);
-	if (bridge == -1) {
-		struct bridge_data *bp;
-
-		if (bus > max_bus || (bp = bridges[bus]) == 0)
-			return 0;
-		return physical ? (void *) bp->io_base_phys : bp->io_base;
+	/* Lookup the "bus-range" property for the hose */		
+	bus_range = (int *) get_property(bridge, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING "Can't get bus-range for %s\n",
+			       bridge->full_name);
+		return;
 	}
-	return physical ? (void *) uninorth_bridges[bridge].iobase_phys
-		: uninorth_bridges[bridge].iobase;
+	bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
 }
 
-__pmac
-void *
-pmac_pci_dev_mem_base(unsigned char bus, unsigned char devfn)
-{
-	return 0;
-}
-
-/* This function only works for bus 0, uni-N uses a different mecanism for
- * other busses (see below)
+/*
+ * Apple MacRISC (UniNorth, Bandit) PCI controllers.
+ * 
+ * The "Bandit" version is present in all early PCI PowerMacs,
+ * and up to the first ones using Grackle. Some machines may
+ * have 2 bandit controllers (2 PCI busses).
+ * 
+ * The "UniNorth" version is present in all Core99 machines
+ * (iBook, G4, new IMacs, and all the recent Apple machines).
+ * It contains 3 controllers in one ASIC.
  */
-#define UNI_N_CFA0(devfn, off)	\
+
+#define MACRISC_CFA0(devfn, off)	\
 	((1 << (unsigned long)PCI_SLOT(dev_fn)) \
 	| (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
 	| (((unsigned long)(off)) & 0xFCUL))
 
-/* This one is for type 1 config accesses */
-#define UNI_N_CFA1(bus, devfn, off)	\
+#define MACRISC_CFA1(bus, devfn, off)	\
 	((((unsigned long)(bus)) << 16) \
 	|(((unsigned long)(devfn)) << 8) \
 	|(((unsigned long)(off)) & 0xFCUL) \
 	|1UL)
 	
-__pmac static
-unsigned int
-uni_north_access_data(unsigned char bus, unsigned char dev_fn,
-				unsigned char offset)
+static unsigned int __pmac
+macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
 {
-	int bridge;
 	unsigned int caddr;
-
-	bridge = pmac_pci_dev_root_bridge(bus, dev_fn);
-	if (bus == 0)
-		caddr = UNI_N_CFA0(dev_fn, offset);
-	else
-		caddr = UNI_N_CFA1(bus, dev_fn, offset);
-	
-	if (bridge == -1) {
-		printk(KERN_WARNING "pmac_pci: no default bridge !\n");
-		return 0;
-	}
-		
-	/* Uninorth will return garbage if we don't read back the value ! */
-	out_le32(uninorth_bridges[bridge].cfg_addr, caddr);
-	(void)in_le32(uninorth_bridges[bridge].cfg_addr);
-	/* Yes, offset is & 7, not & 3 ! */
-	return (unsigned int)(uninorth_bridges[bridge].cfg_data) + (offset & 0x07);
-}
-
-__pmac
-int uni_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned char *val)
-{
-	unsigned int addr;
-	
-	*val = 0xff;
-	addr = uni_north_access_data(bus, dev_fn, offset);
-	if (!addr)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	*val = in_8((volatile unsigned char*)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int uni_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned short *val)
-{
-	unsigned int addr;
-	
-	*val = 0xffff;
-	addr = uni_north_access_data(bus, dev_fn, offset);
-	if (!addr)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	*val = in_le16((volatile unsigned short*)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int uni_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned int *val)
-{
-	unsigned int addr;
-	
-	*val = 0xffff;
-	addr = uni_north_access_data(bus, dev_fn, offset);
-	if (!addr)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	*val = in_le32((volatile unsigned int*)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int uni_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned char val)
-{
-	unsigned int addr;
-	
-	addr = uni_north_access_data(bus, dev_fn, offset);
-	if (!addr)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_8((volatile unsigned char *)addr, val);
-	(void)in_8((volatile unsigned char *)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int uni_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned short val)
-{
-	unsigned int addr;
-	
-	addr = uni_north_access_data(bus, dev_fn, offset);
-	if (!addr)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_le16((volatile unsigned short *)addr, val);
-	(void)in_le16((volatile unsigned short *)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int uni_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-				    unsigned char offset, unsigned int val)
-{
-	unsigned int addr;
 	
-	addr = uni_north_access_data(bus, dev_fn, offset);
-	if (!addr)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_le32((volatile unsigned int *)addr, val);
-	(void)in_le32((volatile unsigned int *)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned char *val)
-{
-	struct bridge_data *bp;
-
-	*val = 0xff;
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (bus == bp->bus_number) {
-		if (dev_fn < (11 << 3))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		out_le32(bp->cfg_addr,
-			 (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
-			 + (offset & ~3));
-	} else {
-		/* Bus number once again taken into consideration.
-		 * Change applied from 2.1.24. This makes devices located
-		 * behind PCI-PCI bridges visible.
-		 * -Ranjit Deshpande, 01/20/99
-		 */
-		out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
-	}
-	udelay(2);
-	*val = in_8(bp->cfg_data + (offset & 3));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned short *val)
-{
-	struct bridge_data *bp;
-
-	*val = 0xffff;
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if ((offset & 1) != 0)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus == bp->bus_number) {
-		if (dev_fn < (11 << 3))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		out_le32(bp->cfg_addr,
-			 (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
-			 + (offset & ~3));
-	} else {
-		/* See pci_read_config_byte */
-		out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
-	}
-	udelay(2);
-	*val = in_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3)));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned int *val)
-{
-	struct bridge_data *bp;
-
-	*val = 0xffffffff;
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if ((offset & 3) != 0)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus == bp->bus_number) {
-		if (dev_fn < (11 << 3))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		out_le32(bp->cfg_addr,
-			 (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
-			 + offset);
-	} else {
-		/* See pci_read_config_byte */
-		out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + offset + 1);
-	}
-	udelay(2);
-	*val = in_le32((volatile unsigned int *)bp->cfg_data);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned char val)
-{
-	struct bridge_data *bp;
-
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (bus == bp->bus_number) {
+#ifdef DEBUG
+//	printk("macrisc_config_access(hose: 0x%08lx, bus: 0x%x, devfb: 0x%x, offset: 0x%x)\n",
+//		hose, bus, dev_fn, offset);
+#endif
+	if (bus == hose->first_busno) {
 		if (dev_fn < (11 << 3))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		out_le32(bp->cfg_addr,
-			 (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
-			 + (offset & ~3));
-	} else {
-		/* See pci_read_config_byte */
-		out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
-	}
-	udelay(2);
-	out_8(bp->cfg_data + (offset & 3), val);
-	return PCIBIOS_SUCCESSFUL;
-}
+			return 0;
+		caddr = MACRISC_CFA0(dev_fn, offset);
+	} else
+		caddr = MACRISC_CFA1(bus, dev_fn, offset);
+	
+	/* Uninorth will return garbage if we don't read back the value ! */
+	do {
+		out_le32(hose->cfg_addr, caddr);
+	} while(in_le32(hose->cfg_addr) != caddr);
+
+	offset &= has_uninorth ? 0x07 : 0x03;
+	return (unsigned int)(hose->cfg_data) + (unsigned int)offset;
+}
+
+#define cfg_read(val, addr, type, op, op2)	\
+	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op, op2)	\
+	op((type *)(addr), (val)); (void) op2((type *)(addr))
+
+#define cfg_read_bad(val, size)		*val = bad_##size;
+#define cfg_write_bad(val, size)
+
+#define bad_byte	0xff
+#define bad_word	0xffff
+#define bad_dword	0xffffffffU
+
+#define MACRISC_PCI_OP(rw, size, type, op, op2)				    \
+static int __pmac							    \
+macrisc_##rw##_config_##size(struct pci_dev *dev, int off, type val)	    \
+{									    \
+	struct pci_controller *hose = dev->sysdata;			    \
+	unsigned int addr;						    \
+									    \
+	addr = macrisc_cfg_access(hose, dev->bus->number, dev->devfn, off); \
+	if (!addr) {							    \
+		cfg_##rw##_bad(val, size)				    \
+		return PCIBIOS_DEVICE_NOT_FOUND;			    \
+	}								    \
+	cfg_##rw(val, addr, type, op, op2);				    \
+	return PCIBIOS_SUCCESSFUL;					    \
+}
+
+MACRISC_PCI_OP(read, byte, u8 *, in_8, x)
+MACRISC_PCI_OP(read, word, u16 *, in_le16, x)
+MACRISC_PCI_OP(read, dword, u32 *, in_le32, x)
+MACRISC_PCI_OP(write, byte, u8, out_8, in_8)
+MACRISC_PCI_OP(write, word, u16, out_le16, in_le16)
+MACRISC_PCI_OP(write, dword, u32, out_le32, in_le32)
+
+static struct pci_ops macrisc_pci_ops =
+{
+	macrisc_read_config_byte,
+	macrisc_read_config_word,
+	macrisc_read_config_dword,
+	macrisc_write_config_byte,
+	macrisc_write_config_word,
+	macrisc_write_config_dword
+};
 
-__pmac
-int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned short val)
-{
-	struct bridge_data *bp;
 
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if ((offset & 1) != 0)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus == bp->bus_number) {
-		if (dev_fn < (11 << 3))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		out_le32(bp->cfg_addr,
-			 (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
-			 + (offset & ~3));
-	} else {
-		/* See pci_read_config_byte */
-		out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
-	}
-	udelay(2);
-	out_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3)), val);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__pmac
-int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-				    unsigned char offset, unsigned int val)
+/*
+ * Apple "Chaos" PCI controller.
+ * 
+ * This controller is present on some first generation "PowerSurge"
+ * machines (8500, 8600, ...). It's a very weird beast and will die
+ * in flames if we try to probe the config space.
+ * The long-term solution is to provide a config space "emulation"
+ * based on what we find in OF device tree
+ */
+ 
+static int chaos_config_read_byte(struct pci_dev *dev, int offset, u8 *val)
 {
-	struct bridge_data *bp;
-
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if ((offset & 3) != 0)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus == bp->bus_number) {
-		if (dev_fn < (11 << 3))
-			return PCIBIOS_DEVICE_NOT_FOUND;
-		out_le32(bp->cfg_addr,
-			 (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)
-			 + offset);
-	} else {
-		/* See pci_read_config_byte */
-		out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);
-	}
-	udelay(2);
-	out_le32((volatile unsigned int *)bp->cfg_data, val);
-	return PCIBIOS_SUCCESSFUL;
+	return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-#define GRACKLE_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
-				 | (((o) & ~3) << 24))
-
-int grackle_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-				     unsigned char offset, unsigned char *val)
+static int chaos_config_read_word(struct pci_dev *dev, int offset, u16 *val)
 {
-	struct bridge_data *bp;
-
-	*val = 0xff;
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
-	*val = in_8(bp->cfg_data + (offset & 3));
-	return PCIBIOS_SUCCESSFUL;
+	return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-int grackle_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-				     unsigned char offset, unsigned short *val)
+static int chaos_config_read_dword(struct pci_dev *dev, int offset, u32 *val)
 {
-	struct bridge_data *bp;
-
-	*val = 0xffff;
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if ((offset & 1) != 0)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
-	*val = in_le16((volatile unsigned short *)(bp->cfg_data + (offset&3)));
-	return PCIBIOS_SUCCESSFUL;
+	return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-int grackle_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-				      unsigned char offset, unsigned int *val)
+static int chaos_config_write_byte(struct pci_dev *dev, int offset, u8 val)
 {
-	struct bridge_data *bp;
-
-	*val = 0xffffffff;
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if ((offset & 3) != 0)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
-	*val = in_le32((volatile unsigned int *)bp->cfg_data);
-	return PCIBIOS_SUCCESSFUL;
+	return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-int grackle_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-				      unsigned char offset, unsigned char val)
+static int chaos_config_write_word(struct pci_dev *dev, int offset, u16 val)
 {
-	struct bridge_data *bp;
-
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
-	out_8(bp->cfg_data + (offset & 3), val);
-	return PCIBIOS_SUCCESSFUL;
+	return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-int grackle_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-				      unsigned char offset, unsigned short val)
+static int chaos_config_write_dword(struct pci_dev *dev, int offset, u32 val)
 {
-	struct bridge_data *bp;
-
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if ((offset & 1) != 0)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
-	out_le16((volatile unsigned short *)(bp->cfg_data + (offset&3)), val);
-	return PCIBIOS_SUCCESSFUL;
+	return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-int grackle_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-				    unsigned char offset, unsigned int val)
+static struct pci_ops chaos_pci_ops =
 {
-	struct bridge_data *bp;
+	chaos_config_read_byte,
+	chaos_config_read_word,
+	chaos_config_read_dword,
+	chaos_config_write_byte,
+	chaos_config_write_word,
+	chaos_config_write_dword
+};
 
-	if (bus > max_bus || (bp = bridges[bus]) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if ((offset & 1) != 0)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
-	out_le32((volatile unsigned int *)bp->cfg_data, val);
-	return PCIBIOS_SUCCESSFUL;
-}
 
 /*
  * For a bandit bridge, turn on cache coherency if necessary.
- * N.B. we can't use pcibios_*_config_* here because bridges[]
- * is not initialized yet.
+ * N.B. we could clean this up using the hose ops directly.
  */
-static void __init init_bandit(struct bridge_data *bp)
+static void __init init_bandit(struct pci_controller *bp)
 {
 	unsigned int vendev, magic;
 	int rev;
@@ -543,8 +258,8 @@
 		rev = in_8(bp->cfg_data);
 		if (rev != BANDIT_REVID)
 			printk(KERN_WARNING
-			       "Unknown revision %d for bandit at %p\n",
-			       rev, bp->io_base);
+			       "Unknown revision %d for bandit at %08lx\n",
+			       rev, bp->io_base_phys);
 	} else if (vendev != (BANDIT_DEVID_2 << 16) + APPLE_VENDID) {
 		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
 		return;
@@ -555,8 +270,8 @@
 	udelay(2);
 	rev = in_8(bp->cfg_data);
 	if (rev != BANDIT_REVID)
-		printk(KERN_WARNING "Unknown revision %d for bandit at %p\n",
-		       rev, bp->io_base);
+		printk(KERN_WARNING "Unknown revision %d for bandit at %08lx\n",
+		       rev, bp->io_base_phys);
 
 	/* read the word at offset 0x50 */
 	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
@@ -567,16 +282,71 @@
 	magic |= BANDIT_COHERENT;
 	udelay(2);
 	out_le32((volatile unsigned int *)bp->cfg_data, magic);
-	printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %p\n",
-	       bp->io_base);
+	printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %08lx\n",
+	       bp->io_base_phys);
+}
+
+
+/*
+ * Tweak the PCI-PCI bridge chip on the blue & white G3s.
+ */
+static void __init
+init_p2pbridge(void)
+{
+	struct device_node *p2pbridge;
+	struct pci_controller* hose;
+	u8 bus, devfn;
+	u16 val;
+
+	/* XXX it would be better here to identify the specific
+	   PCI-PCI bridge chip we have. */
+	if ((p2pbridge = find_devices("pci-bridge")) == 0
+	    || p2pbridge->parent == NULL
+	    || strcmp(p2pbridge->parent->name, "pci") != 0)
+		return;
+	if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
+#ifdef DEBUG
+		printk("Can't find PCI infos for PCI<->PCI bridge\n");
+#endif		
+		return;
+	}
+	/* Warning: At this point, we have not yet renumbered all busses. 
+	 * So we must use OF walking to find out hose
+	 */
+	hose = pci_find_hose_for_OF_device(p2pbridge);
+	if (!hose) {
+#ifdef DEBUG
+		printk("Can't find hose for PCI<->PCI bridge\n");
+#endif		
+		return;
+	}
+	if (early_read_config_word(hose, bus, devfn,
+				   PCI_BRIDGE_CONTROL, &val) < 0) {
+		printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
+		return;
+	}
+	val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
+	early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
 }
 
+void __init
+pmac_find_bridges(void)
+{
+	add_bridges(find_devices("bandit"));
+	add_bridges(find_devices("chaos"));
+	add_bridges(find_devices("pci"));
+	init_p2pbridge();
+}
+
+#define GRACKLE_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
+				 | (((o) & ~3) << 24))
+
 #define GRACKLE_PICR1_STG		0x00000040
 #define GRACKLE_PICR1_LOOPSNOOP		0x00000010
 
 /* N.B. this is called before bridges is initialized, so we can't
    use grackle_pcibios_{read,write}_config_dword. */
-static inline void grackle_set_stg(struct bridge_data *bp, int enable)
+static inline void grackle_set_stg(struct pci_controller* bp, int enable)
 {
 	unsigned int val;
 
@@ -586,9 +356,10 @@
 		(val & ~GRACKLE_PICR1_STG);
 	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
 	out_le32((volatile unsigned int *)bp->cfg_data, val);
+	(void)in_le32((volatile unsigned int *)bp->cfg_data);
 }
 
-static inline void grackle_set_loop_snoop(struct bridge_data *bp, int enable)
+static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)
 {
 	unsigned int val;
 
@@ -598,25 +369,68 @@
 		(val & ~GRACKLE_PICR1_LOOPSNOOP);
 	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
 	out_le32((volatile unsigned int *)bp->cfg_data, val);
+	(void)in_le32((volatile unsigned int *)bp->cfg_data);
 }
 
+static void __init
+setup_uninorth(struct pci_controller* hose, struct reg_property* addr)
+{
+	pci_assign_all_busses = 1;
+	has_uninorth = 1;
+	hose->ops = &macrisc_pci_ops;
+	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+	hose->io_base_phys = addr->address;
+	/* is 0x10000 enough for io space ? */
+	hose->io_base_virt = (void *)ioremap(addr->address, 0x10000);
+
+	/* XXX This is the bridge with the PCI expansion bus. We route
+	 * legacy IOs to it.
+	 */
+	if (addr->address == 0xf2000000)
+		isa_io_base = (unsigned long)hose->io_base_virt;
+}
 
-void __init pmac_find_bridges(void)
+static void __init
+setup_bandit(struct pci_controller* hose, struct reg_property* addr)
 {
-	int bus;
-	struct bridge_data *bridge;
+	hose->ops = &macrisc_pci_ops;
+	hose->cfg_addr = (volatile unsigned int *)
+		ioremap(addr->address + 0x800000, 0x1000);
+	hose->cfg_data = (volatile unsigned char *)
+		ioremap(addr->address + 0xc00000, 0x1000);
+	hose->io_base_phys = addr->address;
+	hose->io_base_virt = (void *) ioremap(addr->address, 0x10000);
+	init_bandit(hose);
+}
+
+static void __init
+setup_chaos(struct pci_controller* hose, struct reg_property* addr)
+{
+	/* assume a `chaos' bridge */
+	hose->ops = &chaos_pci_ops;
+	hose->cfg_addr = (volatile unsigned int *)
+		ioremap(addr->address + 0x800000, 0x1000);
+	hose->cfg_data = (volatile unsigned char *)
+		ioremap(addr->address + 0xc00000, 0x1000);
+	hose->io_base_phys = addr->address;
+	hose->io_base_virt = (void *) ioremap(addr->address, 0x10000);
+}
 
-	bridge_list = 0;
-	max_bus = 0;
-	add_bridges(find_devices("bandit"));
-	add_bridges(find_devices("chaos"));
-	add_bridges(find_devices("pci"));
-	bridges = (struct bridge_data **)
-		alloc_bootmem((max_bus + 1) * sizeof(struct bridge_data *));
-	memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *));
-	for (bridge = bridge_list; bridge != NULL; bridge = bridge->next)
-		for (bus = bridge->bus_number; bus <= bridge->max_bus; ++bus)
-			bridges[bus] = bridge;
+void __init
+setup_grackle(struct pci_controller *hose, unsigned io_space_size)
+{
+	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
+	hose->io_base_phys = 0xfe000000;
+	hose->io_base_virt = (void *) ioremap(0xfe000000, io_space_size);
+	pci_dram_offset = 0;
+	isa_mem_base = 0xfd000000;
+	isa_io_base = (unsigned long) hose->io_base_virt;
+	if (machine_is_compatible("AAPL,PowerBook1998"))
+		grackle_set_loop_snoop(hose, 1);
+#if 0	/* Disabled for now, HW problems ??? */
+	grackle_set_stg(hose, 1);
+#endif
 }
 
 /*
@@ -626,11 +440,12 @@
  */
 static void __init add_bridges(struct device_node *dev)
 {
-	int *bus_range;
 	int len;
-	struct bridge_data *bp;
+	struct pci_controller *hose;
 	struct reg_property *addr;
-
+	char* disp_name;
+	int *bus_range;
+	
 	for (; dev != NULL; dev = dev->next) {
 		addr = (struct reg_property *) get_property(dev, "reg", &len);
 		if (addr == NULL || len < sizeof(*addr)) {
@@ -640,108 +455,52 @@
 		}
 		bus_range = (int *) get_property(dev, "bus-range", &len);
 		if (bus_range == NULL || len < 2 * sizeof(int)) {
-			printk(KERN_WARNING "Can't get bus-range for %s\n",
-			       dev->full_name);
-			continue;
-		}
-		if (bus_range[1] == bus_range[0])
-			printk(KERN_INFO "PCI bus %d", bus_range[0]);
-		else
-			printk(KERN_INFO "PCI buses %d..%d", bus_range[0],
-			       bus_range[1]);
-		printk(" controlled by %s at %x\n", dev->name, addr->address);
-		if (device_is_compatible(dev, "uni-north")) {
-			int i = uninorth_count++;
-			uninorth_bridges[i].cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
-			uninorth_bridges[i].cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
-			uninorth_bridges[i].node = dev;
-			uninorth_bridges[i].iobase_phys = addr->address;
-			/* is 0x10000 enough for io space ? */
-			uninorth_bridges[i].iobase = (void *)ioremap(addr->address, 0x10000);
-			/* XXX This is the bridge with the PCI expansion bus. This is also the
-			 * address of the bus that will receive type 1 config accesses and io
-			 * accesses. Appears to be correct for iMac DV and G4 Sawtooth too.
-			 * That means that we cannot do io cycles on the AGP bus nor the internal
-			 * ethernet/fw bus. Fortunately, they appear not to be needed on iMac DV
-			 * and G4 neither.
-			 */
-			if (addr->address == 0xf2000000)
-				uninorth_default = i;
-			else
-				continue;
+			printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+				       dev->full_name);
 		}
 		
-		bp = (struct bridge_data *) alloc_bootmem(sizeof(*bp));
+		hose = pcibios_alloc_controller();
+		if (!hose)
+			continue;
+		hose->arch_data = dev;
+		hose->first_busno = bus_range ? bus_range[0] : 0;
+		hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+		disp_name = NULL;
 		if (device_is_compatible(dev, "uni-north")) {
-			bp->cfg_addr = 0;
-			bp->cfg_data = 0;
-			bp->io_base = uninorth_bridges[uninorth_count-1].iobase;
-			bp->io_base_phys = uninorth_bridges[uninorth_count-1].iobase_phys;
+			setup_uninorth(hose, addr);
+			disp_name = "UniNorth";
 		} else if (strcmp(dev->name, "pci") == 0) {
 			/* XXX assume this is a mpc106 (grackle) */
-			bp->cfg_addr = (volatile unsigned int *)
-				ioremap(0xfec00000, 0x1000);
-			bp->cfg_data = (volatile unsigned char *)
-				ioremap(0xfee00000, 0x1000);
-			bp->io_base_phys = 0xfe000000;
-                        bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
-                        if (machine_is_compatible("AAPL,PowerBook1998"))
-                        	grackle_set_loop_snoop(bp, 1);
-#if 0 			/* Disabled for now, HW problems ??? */
-			grackle_set_stg(bp, 1);
-#endif
-		} else {
-			/* a `bandit' or `chaos' bridge */
-			bp->cfg_addr = (volatile unsigned int *)
-				ioremap(addr->address + 0x800000, 0x1000);
-			bp->cfg_data = (volatile unsigned char *)
-				ioremap(addr->address + 0xc00000, 0x1000);
-			bp->io_base_phys = addr->address;
-			bp->io_base = (void *) ioremap(addr->address, 0x10000);
+			setup_grackle(hose, 0x20000);
+			disp_name = "Grackle (MPC106)";
+		} else if (strcmp(dev->name, "bandit") == 0) {
+			setup_bandit(hose, addr);
+			disp_name = "Bandit";
+		} else if (strcmp(dev->name, "chaos") == 0) {
+			setup_chaos(hose, addr);
+			disp_name = "Chaos";
 		}
+		printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n",
+			disp_name, addr->address, hose->first_busno, hose->last_busno);
+#ifdef DEBUG
+		printk(" ->Hose at 0x%08lx, cfg_addr=0x%08lx,cfg_data=0x%08lx\n",
+			hose, hose->cfg_addr, hose->cfg_data);
+#endif		
+		
+		/* Setup a default isa_io_base */
 		if (isa_io_base == 0)
-			isa_io_base = (unsigned long) bp->io_base;
-		bp->bus_number = bus_range[0];
-		bp->max_bus = bus_range[1];
-		bp->next = bridge_list;
-		bp->node = dev;
-		bridge_list = bp;
-		if (bp->max_bus > max_bus)
-			max_bus = bp->max_bus;
+			isa_io_base = (unsigned long)hose->io_base_virt;
 
-		if (strcmp(dev->name, "bandit") == 0)
-			init_bandit(bp);
+		/* Fixup "bus-range" OF property */
+		fixup_bus_range(dev);
 	}
 }
 
-/* Recursively searches any node that is of type PCI-PCI bridge. Without
- * this, the old code would miss children of P2P bridges and hence not
- * fix IRQ's for cards located behind P2P bridges.
- * - Ranjit Deshpande, 01/20/99
- */
-void __init
-fix_intr(struct device_node *node, struct pci_dev *dev)
-{
-	unsigned int *reg, *class_code;
-
-	for (; node != 0;node = node->sibling) {
-		class_code = (unsigned int *) get_property(node, "class-code", 0);
-		if(class_code && (*class_code >> 8) == PCI_CLASS_BRIDGE_PCI)
-			fix_intr(node->child, dev);
-		reg = (unsigned int *) get_property(node, "reg", 0);
-		if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn)
-			continue;
-		/* this is the node, see if it has interrupts */
-		if (node->n_intrs > 0) 
-			dev->irq = node->intrs[0].line;
-		break;
-	}
-}
-
-void __init
-pmac_pcibios_fixup(void)
-{
-	struct pci_dev *dev;
+static void
+pcibios_fixup_OF_interrupts(void)
+{	
+	struct pci_dev* dev;
 	
 	/*
 	 * FIXME: This is broken: We should not assign IRQ's to IRQless
@@ -757,44 +516,43 @@
 		 * should find the device node and se if it has an
 		 * AAPL,interrupts property.
 		 */
-		struct bridge_data *bp = bridges[dev->bus->number];
 		unsigned char pin;
+		struct device_node* node;
 			
-		if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||
-		    !pin)
+		if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) || !pin)
 			continue; /* No interrupt generated -> no fixup */
-		/* We iterate all instances of uninorth for now */	
-		if (uninorth_count && dev->bus->number == 0) {
-			int i;
-			for (i=0;i<uninorth_count;i++)
-				fix_intr(uninorth_bridges[i].node->child, dev);
-		} else
-                	fix_intr(bp->node->child, dev);
+		node = pci_device_to_OF_node(dev);
+		if (!node) {
+			printk("No OF node for device %x:%x\n", dev->bus->number, dev->devfn >> 3);
+			continue;
+		}
+		/* this is the node, see if it has interrupts */
+		if (node->n_intrs > 0) 
+			dev->irq = node->intrs[0].line;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 	}
 }
 
 void __init
-pmac_setup_pci_ptrs(void)
+pmac_pcibios_fixup(void)
 {
-	struct device_node* np;
+	/* Fixup interrupts according to OF tree */
+	pcibios_fixup_OF_interrupts();
+}
 
-	np = find_devices("pci");
-	if (np != 0)
-	{
-		if (device_is_compatible(np, "uni-north"))
-		{
-			/* looks like an Core99 powermac */
-			set_config_access_method(uni);
-		} else
-		{
-			/* looks like a G3 powermac */
-			set_config_access_method(grackle);
-		}
-	} else
-	{
-		set_config_access_method(pmac);
+/* We don't want to enable USB controllers absent from the OF tree
+ * (iBook second controller)
+ */
+int
+pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
+{
+	if (dev->vendor == PCI_VENDOR_ID_APPLE
+	    && dev->device == PCI_DEVICE_ID_APPLE_KL_USB) {
+		struct device_node* node;
+		node = pci_device_to_OF_node(dev);
+		if (!node)
+			return -EINVAL;
 	}
-	
-	ppc_md.pcibios_fixup = pmac_pcibios_fixup;
+	return 0;
 }
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.4.0/linux/arch/ppc/kernel/pmac_pic.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/pmac_pic.c	Mon Jan 22 15:41:15 2001
@@ -4,14 +4,15 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/pci.h>
-#include <linux/openpic.h>
 
 #include <asm/init.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
+
 #include "pmac_pic.h"
+#include "open_pic.h"
 
 /* pmac */struct pmac_irq_hw {
         unsigned int    flag;
@@ -30,16 +31,14 @@
 
 static int max_irqs;
 static int max_real_irqs;
-static int has_openpic = 0;
+static int pmac_has_openpic;
+
+spinlock_t pmac_pic_lock = SPIN_LOCK_UNLOCKED;
+
 
 #define GATWICK_IRQ_POOL_SIZE        10
 static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
 
-extern int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-                                      unsigned char offset, unsigned short *val);
-extern int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-                                      unsigned char offset, unsigned short val);
-
 /*
  * Mark an irq as "lost".  This is only used on the pmac
  * since it can lose interrupts (see pmac_set_irq_mask).
@@ -51,48 +50,11 @@
 		atomic_inc(&ppc_n_lost_interrupts);
 }
 
-static void pmac_openpic_mask_irq(unsigned int irq_nr)
-{
-	openpic_disable_irq(irq_nr);
-}
-
-static void pmac_openpic_unmask_irq(unsigned int irq_nr)
-{
-	openpic_enable_irq(irq_nr);
-}
-
-static void pmac_openpic_ack_irq(unsigned int irq_nr)
-{
-	if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
-		openpic_eoi(smp_processor_id());
-	openpic_disable_irq(irq_nr);
-}
-
-static void pmac_openpic_end_irq(unsigned int irq_nr)
-{
-	if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0)
-		openpic_eoi(smp_processor_id());
-	openpic_enable_irq(irq_nr);
-}
-
-struct hw_interrupt_type pmac_open_pic = {
-	" OpenPIC  ",
-	NULL,
-	NULL,
-	pmac_openpic_unmask_irq,
-	pmac_openpic_mask_irq,
-	/* Theorically, the mask&ack should be NULL for OpenPIC. However, doing
-	 * so shows tons of bogus interrupts coming in.
-	 */
-	pmac_openpic_ack_irq,
-	pmac_openpic_end_irq,
-	NULL
-};
-
 static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr)
 {
         unsigned long bit = 1UL << (irq_nr & 0x1f);
         int i = irq_nr >> 5;
+        unsigned long flags;
 
         if ((unsigned)irq_nr >= max_irqs)
                 return;
@@ -100,6 +62,7 @@
         clear_bit(irq_nr, ppc_cached_irq_mask);
         if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
                 atomic_dec(&ppc_n_lost_interrupts);
+	spin_lock_irqsave(&pmac_pic_lock, flags);
         out_le32(&pmac_irq_hw[i]->ack, bit);
         out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
         out_le32(&pmac_irq_hw[i]->ack, bit);
@@ -108,16 +71,19 @@
                    interrupts */
                 mb();
         } while(in_le32(&pmac_irq_hw[i]->flag) & bit);
+	spin_unlock_irqrestore(&pmac_pic_lock, flags);
 }
 
 static void __pmac pmac_set_irq_mask(unsigned int irq_nr)
 {
         unsigned long bit = 1UL << (irq_nr & 0x1f);
         int i = irq_nr >> 5;
+        unsigned long flags;
 
         if ((unsigned)irq_nr >= max_irqs)
                 return;
 
+	spin_lock_irqsave(&pmac_pic_lock, flags);
         /* enable unmasked interrupts */
         out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
 
@@ -137,6 +103,7 @@
             && (ld_le32(&pmac_irq_hw[i]->level) & bit)
             && !(ld_le32(&pmac_irq_hw[i]->flag) & bit))
 		__set_lost((ulong)irq_nr);
+	spin_unlock_irqrestore(&pmac_pic_lock, flags);
 }
 
 static void __pmac pmac_mask_irq(unsigned int irq_nr)
@@ -152,6 +119,15 @@
         pmac_set_irq_mask(irq_nr);
 }
 
+static void __pmac pmac_end_irq(unsigned int irq_nr)
+{
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+        	set_bit(irq_nr, ppc_cached_irq_mask);
+	        pmac_set_irq_mask(irq_nr);
+	}
+}
+
+
 struct hw_interrupt_type pmac_pic = {
         " PMAC-PIC ",
         NULL,
@@ -159,7 +135,7 @@
         pmac_unmask_irq,
         pmac_mask_irq,
         pmac_mask_and_ack_irq,
-        pmac_unmask_irq,
+        pmac_end_irq,
         NULL
 };
 
@@ -170,7 +146,7 @@
 	pmac_unmask_irq,
 	pmac_mask_irq,
 	pmac_mask_and_ack_irq,
-	pmac_unmask_irq,
+	pmac_end_irq,
 	NULL
 };
 
@@ -204,35 +180,22 @@
 	unsigned long bits = 0;
 
 #ifdef CONFIG_SMP
-	void pmac_smp_message_recv(struct pt_regs *);
+	void psurge_smp_message_recv(struct pt_regs *);
 	
-        /* IPI's are a hack on the powersurge -- Cort */
-        if ( smp_processor_id() != 0 )
-        {
-		pmac_smp_message_recv(regs);
+       	/* IPI's are a hack on the powersurge -- Cort */
+       	if ( smp_processor_id() != 0 ) {
+		psurge_smp_message_recv(regs);
 		return -2;	/* ignore, already handled */
         }
 #endif /* CONFIG_SMP */
-
-	if (has_openpic) {
-		irq = openpic_irq(smp_processor_id());
-		if (irq == OPENPIC_VEC_SPURIOUS)
-			/* We get those when doing polled ADB requests,
-			 * using -2 is a temp hack to disable the printk
-			 */
-			irq = -2; /*-1; */
-	}
-	else
-	{
-		for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
-			int i = irq >> 5;
-			bits = ld_le32(&pmac_irq_hw[i]->flag)
-				| ppc_lost_interrupts[i];
-			if (bits == 0)
-				continue;
-			irq += __ilog2(bits);
-			break;
-		}
+	for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
+		int i = irq >> 5;
+		bits = ld_le32(&pmac_irq_hw[i]->flag)
+			| ppc_lost_interrupts[i];
+		if (bits == 0)
+			continue;
+		irq += __ilog2(bits);
+		break;
 	}
 
 	return irq;
@@ -336,11 +299,16 @@
 	addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
 	pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
 	max_irqs = 64;
-	if (pci_device_loc(irqctrler, &bus, &devfn) == 0) {
-		pmac_pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
-		cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
-		cmd &= ~PCI_COMMAND_IO;
-		pmac_pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+	if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {
+		struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);
+		if (!hose)
+		    printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
+		else {
+		    early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
+		    cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+	  	    cmd &= ~PCI_COMMAND_IO;
+		    early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
+		}
 	}
 
 	second_irq = irqctrler->intrs[0].line;
@@ -378,20 +346,26 @@
 		printk("PowerMac using OpenPIC irq controller\n");
 		if (irqctrler->n_addrs > 0)
 		{
+			int nmi_irq = -1;
+			unsigned char senses[NR_IRQS];
 #ifdef CONFIG_XMON
 			struct device_node* pswitch;
-#endif /* CONFIG_XMON */	
-			OpenPIC = (volatile struct OpenPIC *)
-				ioremap(irqctrler->addrs[0].address,
-					irqctrler->addrs[0].size);
-			for ( i = 0 ; i < NR_IRQS ; i++ )
-				irq_desc[i].handler = &pmac_open_pic;
-			openpic_init(1);
-			has_openpic = 1;
-#ifdef CONFIG_XMON
+
 			pswitch = find_devices("programmer-switch");
 			if (pswitch && pswitch->n_intrs)
-				request_irq(pswitch->intrs[0].line, xmon_irq, 0,
+				nmi_irq = pswitch->intrs[0].line;
+#endif /* CONFIG_XMON */
+			prom_get_irq_senses(senses, 0, NR_IRQS);
+			OpenPIC_InitSenses = senses;
+			OpenPIC_NumInitSenses = NR_IRQS;
+			ppc_md.get_irq = openpic_get_irq;
+			OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
+					       irqctrler->addrs[0].size);
+			openpic_init(1, 0, 0, nmi_irq);
+			pmac_has_openpic = 1;
+#ifdef CONFIG_XMON
+			if (nmi_irq >= 0)
+				request_irq(nmi_irq, xmon_irq, 0,
 					    "NMI - XMON", 0);
 #endif	/* CONFIG_XMON */
 			return;
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.4.0/linux/arch/ppc/kernel/pmac_setup.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/pmac_setup.c	Mon Jan 22 15:41:15 2001
@@ -47,6 +47,7 @@
 #include <linux/cuda.h>
 #include <linux/pmu.h>
 
+#include <asm/processor.h>
 #include <asm/init.h>
 #include <asm/prom.h>
 #include <asm/system.h>
@@ -73,7 +74,8 @@
 extern int pmac_set_rtc_time(unsigned long nowtime);
 extern void pmac_read_rtc_time(void);
 extern void pmac_calibrate_decr(void);
-extern void pmac_setup_pci_ptrs(void);
+extern void pmac_pcibios_fixup(void);
+extern void pmac_find_bridges(void);
 
 extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int mackbd_getkeycode(unsigned int scancode);
@@ -99,9 +101,7 @@
 extern int keyboard_sends_linux_keycodes;
 extern void pmac_nvram_update(void);
 
-extern void *pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical);
-extern void *pmac_pci_dev_mem_base(unsigned char bus, unsigned char devfn);
-extern int pmac_pci_dev_root_bridge(unsigned char bus, unsigned char devfn);
+extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
 
 unsigned char drive_info;
 
@@ -119,13 +119,34 @@
 
 extern void zs_kgdb_hook(int tty_num);
 static void ohare_init(void);
-static void init_p2pbridge(void);
 #ifdef CONFIG_BOOTX_TEXT
 void pmac_progress(char *s, unsigned short hex);
 #endif
 
 sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
 
+#ifdef CONFIG_SMP
+volatile static long int core99_l2_cache;
+void core99_init_l2(void)
+{
+	int cpu = smp_processor_id();
+
+	if ( (_get_PVR() >> 16) != 8 && (_get_PVR() >> 16) != 12 )
+		return;
+
+	if (cpu == 0){
+		core99_l2_cache = _get_L2CR();
+		printk("CPU0: L2CR is %lx\n", core99_l2_cache);
+	} else {
+		printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
+		_set_L2CR(0);
+		_set_L2CR(core99_l2_cache);
+		printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
+	}
+}
+#endif /* CONFIG_SMP */
+
+
 __pmac
 int
 pmac_get_cpuinfo(char *buffer)
@@ -250,7 +271,7 @@
 	struct device_node *cpu;
 	int *fp;
 
-	/* Set loops_per_sec to a half-way reasonable value,
+	/* Set loops_per_jiffy to a half-way reasonable value,
 	   for use until calibrate_delay gets called. */
 	cpu = find_type_devices("cpu");
 	if (cpu != 0) {
@@ -263,13 +284,13 @@
 			case 10:	/* mach V (604ev5) */
 			case 12:	/* G4 */
 			case 20:	/* 620 */
-				loops_per_sec = *fp;
+				loops_per_jiffy = *fp / HZ;
 				break;
 			default:	/* 601, 603, etc. */
-				loops_per_sec = *fp / 2;
+				loops_per_jiffy = *fp / (2*HZ);
 			}
 		} else
-			loops_per_sec = 50000000;
+			loops_per_jiffy = 50000000 / HZ;
 	}
 
 	/* this area has the CPU identification register
@@ -278,8 +299,8 @@
 	__ioremap(0xffc00000, 0x400000, pgprot_val(PAGE_READONLY));
 	ohare_init();
 
+	/* Lookup PCI hosts */
 	pmac_find_bridges();
-	init_p2pbridge();
 	
 	/* Checks "l2cr-value" property in the registry */
 	if ( (_get_PVR() >> 16) == 8 || (_get_PVR() >> 16) == 12 ) {
@@ -303,6 +324,11 @@
 			ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
 				? "enabled" : "disabled");
 
+#ifdef CONFIG_SMP
+	/* somewhat of a hack */
+	core99_init_l2();
+#endif
+	
 #ifdef CONFIG_KGDB
 	zs_kgdb_hook(0);
 #endif
@@ -330,32 +356,6 @@
 		ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
 }
 
-/*
- * Tweak the PCI-PCI bridge chip on the blue & white G3s.
- */
-static void __init init_p2pbridge(void)
-{
-	struct device_node *p2pbridge;
-	unsigned char bus, devfn;
-	unsigned short val;
-
-	/* XXX it would be better here to identify the specific
-	   PCI-PCI bridge chip we have. */
-	if ((p2pbridge = find_devices("pci-bridge")) == 0
-	    || p2pbridge->parent == NULL
-	    || strcmp(p2pbridge->parent->name, "pci") != 0)
-		return;
-	if (pci_device_loc(p2pbridge, &bus, &devfn) < 0)
-		return;
-	if (ppc_md.pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val) < 0) {
-		printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
-		return;
-	}
-	val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
-	ppc_md.pcibios_write_config_word(bus, devfn, PCI_BRIDGE_CONTROL, val);
-	ppc_md.pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val);
-}
-
 static void __init ohare_init(void)
 {
 	/*
@@ -448,7 +448,7 @@
 
 void __init find_boot_device(void)
 {
-#ifdef CONFIG_SCSI
+#if defined(CONFIG_SCSI) && defined(CONFIG_BLK_DEV_SD)
 	if (boot_host != NULL) {
 		boot_dev = sd_find_target(boot_host, boot_target);
 		if (boot_dev != 0)
@@ -493,7 +493,9 @@
 	struct adb_request req;
 #endif /* CONFIG_ADB_CUDA */
 
+#ifdef CONFIG_NVRAM
 	pmac_nvram_update();
+#endif
 	
 	switch (sys_ctrler) {
 #ifdef CONFIG_ADB_CUDA
@@ -509,7 +511,7 @@
 		pmu_restart();
 		break;
 #endif /* CONFIG_ADB_PMU */		
-	default:
+	default: ;
 	}
 }
 
@@ -520,7 +522,9 @@
 	struct adb_request req;
 #endif /* CONFIG_ADB_CUDA */
 
+#ifdef CONFIG_NVRAM
 	pmac_nvram_update();
+#endif
 	
 	switch (sys_ctrler) {
 #ifdef CONFIG_ADB_CUDA
@@ -536,7 +540,7 @@
 		pmu_shutdown();
 		break;
 #endif /* CONFIG_ADB_PMU */
-	default:
+	default: ;
 	}
 }
 
@@ -566,17 +570,19 @@
 int
 pmac_ide_default_irq(ide_ioreg_t base)
 {
-        return 0;
-}
-
 #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-extern ide_ioreg_t pmac_ide_get_base(int index);
+	extern int pmac_ide_get_irq(ide_ioreg_t base);
+        return pmac_ide_get_irq(base);
+#else
+	return 0;
 #endif
+}
 
 ide_ioreg_t
 pmac_ide_default_io_base(int index)
 {
 #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
+	extern ide_ioreg_t pmac_ide_get_base(int index);
         return pmac_ide_get_base(index);
 #else
 	return 0;
@@ -586,7 +592,14 @@
 int
 pmac_ide_check_region(ide_ioreg_t from, unsigned int extent)
 {
-        return 0;
+	/*
+	 * We only do the check_region if `from' looks like a genuine
+	 * I/O port number.  If it actually refers to a memory-mapped
+	 * register, it should be OK.
+	 */
+	if (from < ~_IO_BASE)
+		return 0;
+	return check_region(from, extent);
 }
 
 void
@@ -594,24 +607,16 @@
 			unsigned int extent,
 			const char *name)
 {
+	if (from < ~_IO_BASE)
+		request_region(from, extent, name);
 }
 
 void
 pmac_ide_release_region(ide_ioreg_t from,
 			unsigned int extent)
 {
-}
-
-/* Convert the shorts/longs in hd_driveid from little to big endian;
- * chars are endian independant, of course, but strings need to be flipped.
- * (Despite what it says in drivers/block/ide.h, they come up as little
- * endian...)
- *
- * Changes to linux/hdreg.h may require changes here. */
-void
-pmac_ide_fix_driveid(struct hd_driveid *id)
-{
-        ppc_generic_ide_fix_driveid(id);
+	if (from < ~_IO_BASE)
+		release_region(from, extent);
 }
 
 #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
@@ -632,8 +637,6 @@
 pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	  unsigned long r6, unsigned long r7)
 {
-	pmac_setup_pci_ptrs();
-
 	/* isa_io_base gets set in pmac_find_bridges */
 	isa_mem_base = PMAC_ISA_MEM_BASE;
 	pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
@@ -646,8 +649,11 @@
 	ppc_md.get_cpuinfo    = pmac_get_cpuinfo;
 	ppc_md.irq_cannonicalize = NULL;
 	ppc_md.init_IRQ       = pmac_pic_init;
-	ppc_md.get_irq        = pmac_get_irq;
+	ppc_md.get_irq        = pmac_get_irq; /* Changed later on ... */
 	ppc_md.init           = pmac_init2;
+	
+	ppc_md.pcibios_fixup  = pmac_pcibios_fixup;
+	ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
 
 	ppc_md.restart        = pmac_restart;
 	ppc_md.power_off      = pmac_power_off;
@@ -658,12 +664,8 @@
 	ppc_md.get_rtc_time   = pmac_get_rtc_time;
 	ppc_md.calibrate_decr = pmac_calibrate_decr;
 
-	ppc_md.pci_dev_io_base          = pmac_pci_dev_io_base;
-	ppc_md.pci_dev_mem_base         = pmac_pci_dev_mem_base;
-	ppc_md.pci_dev_root_bridge      = pmac_pci_dev_root_bridge;
-
 #ifdef CONFIG_VT
-#ifdef CONFIG_INPUT_ADBHID
+#ifdef CONFIG_INPUT
 	ppc_md.kbd_init_hw       = mac_hid_init_hw;
 	ppc_md.kbd_translate     = mac_hid_kbd_translate;
 	ppc_md.kbd_unexpected_up = mac_hid_kbd_unexpected_up;
@@ -682,35 +684,33 @@
 	}
 #endif /* CONFIG_MAGIC_SYSRQ */
 #elif defined(CONFIG_ADB_KEYBOARD)
-	ppc_md.kbd_setkeycode    = mackbd_setkeycode;
-	ppc_md.kbd_getkeycode    = mackbd_getkeycode;
-	ppc_md.kbd_translate     = mackbd_translate;
-	ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
-	ppc_md.kbd_leds          = mackbd_leds;
-	ppc_md.kbd_init_hw       = mackbd_init_hw;
+	ppc_md.kbd_setkeycode       = mackbd_setkeycode;
+	ppc_md.kbd_getkeycode       = mackbd_getkeycode;
+	ppc_md.kbd_translate        = mackbd_translate;
+	ppc_md.kbd_unexpected_up    = mackbd_unexpected_up;
+	ppc_md.kbd_leds             = mackbd_leds;
+	ppc_md.kbd_init_hw          = mackbd_init_hw;
 #ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.ppc_kbd_sysrq_xlate       = mackbd_sysrq_xlate;
+	ppc_md.ppc_kbd_sysrq_xlate  = mackbd_sysrq_xlate;
 	SYSRQ_KEY = 0x69;
 #endif /* CONFIG_MAGIC_SYSRQ */
 #endif /* CONFIG_INPUT_ADBHID/CONFIG_ADB_KEYBOARD */
 #endif /* CONFIG_VT */
 
 #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-        ppc_ide_md.insw = pmac_ide_insw;
-        ppc_ide_md.outsw = pmac_ide_outsw;
-        ppc_ide_md.default_irq = pmac_ide_default_irq;
-        ppc_ide_md.default_io_base = pmac_ide_default_io_base;
-        ppc_ide_md.ide_check_region = pmac_ide_check_region;
-        ppc_ide_md.ide_request_region = pmac_ide_request_region;
-        ppc_ide_md.ide_release_region = pmac_ide_release_region;
-        ppc_ide_md.fix_driveid = pmac_ide_fix_driveid;
-        ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
-
-        ppc_ide_md.io_base = _IO_BASE;	/* actually too early for this :-( */
-#endif
+        ppc_ide_md.insw			= pmac_ide_insw;
+        ppc_ide_md.outsw		= pmac_ide_outsw;
+        ppc_ide_md.default_irq		= pmac_ide_default_irq;
+        ppc_ide_md.default_io_base	= pmac_ide_default_io_base;
+        ppc_ide_md.ide_check_region	= pmac_ide_check_region;
+        ppc_ide_md.ide_request_region	= pmac_ide_request_region;
+        ppc_ide_md.ide_release_region	= pmac_ide_release_region;
+        ppc_ide_md.fix_driveid		= ppc_generic_ide_fix_driveid;
+        ppc_ide_md.ide_init_hwif	= pmac_ide_init_hwif_ports;
+#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
 #ifdef CONFIG_BOOTX_TEXT
 	ppc_md.progress = pmac_progress;
-#endif
+#endif /* CONFIG_BOOTX_TEXT */
 	if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
 	
 }
@@ -727,5 +727,5 @@
 	prom_drawstring(s);
 	prom_drawchar('\n');
 }
-#endif CONFIG_BOOTX_TEXT
+#endif /* CONFIG_BOOTX_TEXT */
 
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c
--- v2.4.0/linux/arch/ppc/kernel/pmac_time.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/pmac_time.c	Mon Jan 22 15:41:15 2001
@@ -114,7 +114,7 @@
 			+ (req.reply[3] << 8) + req.reply[4];
 		return now - RTC_OFFSET;
 #endif /* CONFIG_ADB_PMU */
-	default:
+	default: ;
 	}
 	return 0;
 }
@@ -135,7 +135,7 @@
 			return 0;
 		while (!req.complete)
 			cuda_poll();
-//		if (req.reply_len != 7)
+		if ((req.reply_len != 3) && (req.reply_len != 7))
 			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
 			       req.reply_len);
 		return 1;
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/ppc_asm.h linux/arch/ppc/kernel/ppc_asm.h
--- v2.4.0/linux/arch/ppc/kernel/ppc_asm.h	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/kernel/ppc_asm.h	Mon Jan 22 15:41:15 2001
@@ -50,7 +50,7 @@
  */
 #define LVX(r,a,b)	.long	(31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(103<<1)
 #define STVX(r,a,b)	.long	(31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(231<<1)
-#define MFVSCR(r)	.long	(4<<26)+((r)<<21)+(1540<<1)
+#define MFVSCR(r)	.long	(4<<26)+((r)<<21)+(770<<1)
 #define MTVSCR(r)	.long	(4<<26)+((r)<<11)+(802<<1)
 
 #define SAVE_VR(n,b,base)	li b,THREAD_VR0+(16*(n)); STVX(n,b,base)
@@ -66,9 +66,13 @@
 #define REST_16VR(n,b,base)	REST_8VR(n,b,base); REST_8VR(n+8,b,base) 
 #define REST_32VR(n,b,base)	REST_16VR(n,b,base); REST_16VR(n+16,b,base)
 
+#ifdef CONFIG_PPC601_SYNC_FIX
 #define SYNC \
 	sync; \
 	isync
+#else
+#define	SYNC
+#endif
 
 /*
  * This instruction is not implemented on the PPC 603 or 601; however, on
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- v2.4.0/linux/arch/ppc/kernel/ppc_htab.c	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/kernel/ppc_htab.c	Mon Jan 22 15:41:15 2001
@@ -555,10 +555,7 @@
 				break;
 			buffer += len;
 			left -= len;
-			_set_L2CR(0);
 			_set_L2CR(val);
-			while ( _get_L2CR() & 0x1 )
-				/* wait for invalidate to finish */;
 			  
 		} else {
 			p = buf;
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.4.0/linux/arch/ppc/kernel/ppc_ksyms.c	Sat Nov 11 18:23:10 2000
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon Jan 22 15:41:15 2001
@@ -12,6 +12,7 @@
 #include <linux/console.h>
 #include <linux/irq.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 
 #include <asm/page.h>
 #include <asm/semaphore.h>
@@ -40,6 +41,7 @@
 #include <asm/backlight.h>
 #ifdef CONFIG_SMP
 #include <asm/smplock.h>
+#include <asm/smp.h>
 #endif /* CONFIG_SMP */
 #include <asm/time.h>
 
@@ -53,9 +55,10 @@
 extern void AlignmentException(struct pt_regs *regs);
 extern void ProgramCheckException(struct pt_regs *regs);
 extern void SingleStepException(struct pt_regs *regs);
-extern int sys_sigreturn(struct pt_regs *regs);
 extern void do_lost_interrupts(unsigned long);
 extern int do_signal(sigset_t *, struct pt_regs *);
+extern int pmac_newworld;
+extern int sys_sigreturn(struct pt_regs *regs);
 
 long long __ashrdi3(long long, int);
 long long __ashldi3(long long, int);
@@ -98,10 +101,6 @@
 EXPORT_SYMBOL(ucSystemType);
 #endif
 #endif
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pci_dev_io_base);
-EXPORT_SYMBOL(pci_dev_mem_base);
-#endif
 
 #if !__INLINE_BITOPS
 EXPORT_SYMBOL(set_bit);
@@ -125,6 +124,7 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strcasecmp);
 
 /* EXPORT_SYMBOL(csum_partial); already in net/netsyms.c */
 EXPORT_SYMBOL(csum_partial_copy_generic);
@@ -202,6 +202,10 @@
 EXPORT_SYMBOL(_read_unlock);
 EXPORT_SYMBOL(_write_lock);
 EXPORT_SYMBOL(_write_unlock);
+EXPORT_SYMBOL(smp_call_function);
+EXPORT_SYMBOL(smp_hw_index);
+EXPORT_SYMBOL(smp_num_cpus);
+EXPORT_SYMBOL(synchronize_irq);
 #endif
 
 #ifndef CONFIG_MACH_SPECIFIC
@@ -234,12 +238,14 @@
 #ifdef CONFIG_PMAC_BACKLIGHT
 EXPORT_SYMBOL(get_backlight_level);
 EXPORT_SYMBOL(set_backlight_level);
+EXPORT_SYMBOL(set_backlight_enable);
+EXPORT_SYMBOL(register_backlight_controller);
 #endif /* CONFIG_PMAC_BACKLIGHT */
-#if defined(CONFIG_ALL_PPC)
 EXPORT_SYMBOL_NOVERS(sys_ctrler);
 #ifndef CONFIG_MACH_SPECIFIC
 EXPORT_SYMBOL_NOVERS(have_of);
 #endif /* CONFIG_MACH_SPECIFIC */
+#if defined(CONFIG_ALL_PPC)
 EXPORT_SYMBOL(find_devices);
 EXPORT_SYMBOL(find_type_devices);
 EXPORT_SYMBOL(find_compatible_devices);
@@ -247,18 +253,29 @@
 EXPORT_SYMBOL(find_phandle);
 EXPORT_SYMBOL(device_is_compatible);
 EXPORT_SYMBOL(machine_is_compatible);
-EXPORT_SYMBOL(find_pci_device_OFnode);
 EXPORT_SYMBOL(find_all_nodes);
 EXPORT_SYMBOL(get_property);
-EXPORT_SYMBOL(pci_io_base);
-EXPORT_SYMBOL(pci_device_loc);
+EXPORT_SYMBOL(pci_bus_io_base);
+EXPORT_SYMBOL(pci_bus_io_base_phys);
+EXPORT_SYMBOL(pci_bus_mem_base_phys);
+EXPORT_SYMBOL(pci_device_to_OF_node);
+EXPORT_SYMBOL(pci_device_from_OF_node);
+EXPORT_SYMBOL(pci_bus_to_hose);
+EXPORT_SYMBOL(pci_resource_to_bus);
+EXPORT_SYMBOL(pci_phys_to_bus);
+EXPORT_SYMBOL(pci_bus_to_phys);
+EXPORT_SYMBOL(pmac_newworld);
 EXPORT_SYMBOL(feature_set);
 EXPORT_SYMBOL(feature_clear);
 EXPORT_SYMBOL(feature_test);
 EXPORT_SYMBOL(feature_set_gmac_power);
+EXPORT_SYMBOL(feature_set_gmac_phy_reset);
 EXPORT_SYMBOL(feature_set_usb_power);
 EXPORT_SYMBOL(feature_set_firewire_power);
 #endif /* defined(CONFIG_ALL_PPC) */
+#if defined(CONFIG_BOOTX_TEXT)
+EXPORT_SYMBOL(bootx_update_display);
+#endif
 #if defined(CONFIG_SCSI) && defined(CONFIG_ALL_PPC)
 EXPORT_SYMBOL(note_scsi_host);
 #endif
@@ -286,6 +303,7 @@
 EXPORT_SYMBOL(screen_info);
 #endif
 
+EXPORT_SYMBOL(__delay);
 EXPORT_SYMBOL(int_control);
 EXPORT_SYMBOL(timer_interrupt_intercept);
 EXPORT_SYMBOL(timer_interrupt);
@@ -300,6 +318,10 @@
 #ifdef CONFIG_XMON
 EXPORT_SYMBOL(xmon);
 #endif
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_trylock);
 EXPORT_SYMBOL(down_read_failed);
 EXPORT_SYMBOL(down_write_failed);
 
@@ -324,6 +346,12 @@
 EXPORT_SYMBOL(next_mmu_context);
 EXPORT_SYMBOL(set_context);
 EXPORT_SYMBOL(mmu_context_overflow);
+#if !defined(CONFIG_8xx) && !defined(CONFIG_4xx)
+extern long *intercept_table;
+EXPORT_SYMBOL(intercept_table);
+#endif
+extern long *ret_from_intercept;
+EXPORT_SYMBOL(ret_from_intercept);
 
 #ifdef CONFIG_MOL
 extern ulong mol_interface[];
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/prep_nvram.c linux/arch/ppc/kernel/prep_nvram.c
--- v2.4.0/linux/arch/ppc/kernel/prep_nvram.c	Thu Oct  7 10:17:08 1999
+++ linux/arch/ppc/kernel/prep_nvram.c	Mon Jan 22 15:41:15 2001
@@ -16,19 +16,9 @@
 #include <asm/machdep.h>
 #include <asm/prep_nvram.h>
 
-/*
- * Allow for a maximum of 32K of PReP NvRAM data
- */
-#define MAX_PREP_NVRAM 0x8000
 static char nvramData[MAX_PREP_NVRAM];
 static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0];
 
-#define PREP_NVRAM_AS0	0x74
-#define PREP_NVRAM_AS1	0x75
-#define PREP_NVRAM_DATA	0x77
-
-unsigned char *rs_pcNvRAM;
-
 unsigned char __prep prep_nvram_read_val(int addr)
 {
 	outb(addr, PREP_NVRAM_AS0);
@@ -44,36 +34,12 @@
    	outb(val, PREP_NVRAM_DATA);
 }
   
-/*
- * Most Radstone boards have NvRAM memory mapped at offset 8M in ISA space
- */
-unsigned char __prep rs_nvram_read_val(int addr)
-{
-	return rs_pcNvRAM[addr];
-}
-  
-void __prep rs_nvram_write_val(int addr,
-			unsigned char val)
-{
-	rs_pcNvRAM[addr]=val;
-}
-  
 void __init init_prep_nvram(void)
 {
 	unsigned char *nvp;
 	int  i;
 	int  nvramSize;
 
-	/*
-	 * I'm making the assumption that 32k will always cover the
-	 * nvramsize.  If this isn't the case please let me know and we can
-	 * map the header, then get the size from the header, then map
-	 * the whole size. -- Cort
-	 */
-	if ( _prep_type == _PREP_Radstone )
-		rs_pcNvRAM = (unsigned char *)ioremap(_ISA_MEM_BASE+0x00800000,
-						      32<<10);
-	request_region(PREP_NVRAM_AS0, 0x8, "PReP NVRAM");
 	/*
 	 * The following could fail if the NvRAM were corrupt but
 	 * we expect the boot firmware to have checked its checksum
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.4.0/linux/arch/ppc/kernel/prep_pci.c	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/kernel/prep_pci.c	Wed Jan 24 15:28:36 2001
@@ -7,11 +7,11 @@
  * The motherboard routes/maps will disappear shortly. -- Cort
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/openpic.h>
 
 #include <asm/init.h>
 #include <asm/byteorder.h>
@@ -25,6 +25,7 @@
 #include <asm/machdep.h>
 
 #include "pci.h"
+#include "open_pic.h"
 
 #define MAX_DEVNR 22
 
@@ -39,9 +40,6 @@
 /* Used for Motorola to store system config register */
 static unsigned long	*ProcInfo;
 
-extern int chrp_get_irq(struct pt_regs *);
-extern void chrp_post_irq(struct pt_regs* regs, int);
-
 /* Tables for known hardware */   
 
 /* Motorola PowerStackII - Utah */
@@ -534,128 +532,45 @@
 #define CFGPTR(dev) (0x80800000 | (1<<(dev>>3)) | ((dev&7)<<8) | offset)
 #define DEVNO(dev)  (dev>>3)                                  
 
-__prep
-int
-prep_pcibios_read_config_dword (unsigned char bus,
-			   unsigned char dev, unsigned char offset, unsigned int *val)
-{
-	unsigned long _val;                                          
-	unsigned long *ptr;
-
-	if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
-	{                   
-		*val = 0xFFFFFFFF;
-		return PCIBIOS_DEVICE_NOT_FOUND;    
-	} else                                                                
-	{
-		ptr = (unsigned long *)CFGPTR(dev);
-		_val = le32_to_cpu(*ptr);
-	}
-	*val = _val;
-	return PCIBIOS_SUCCESSFUL;
-}
+#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
 
-__prep
-int
-prep_pcibios_read_config_word (unsigned char bus,
-			  unsigned char dev, unsigned char offset, unsigned short *val)
-{
-	unsigned short _val;                                          
-	unsigned short *ptr;
-
-	if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
-	{                   
-		*val = 0xFFFF;
-		return PCIBIOS_DEVICE_NOT_FOUND;    
-	} else                                                                
-	{
-		ptr = (unsigned short *)CFGPTR(dev);
-		_val = le16_to_cpu(*ptr);
-	}
-	*val = _val;
-	return PCIBIOS_SUCCESSFUL;
-}
+#define cfg_read_bad(val, size)		*val = bad_##size;
+#define cfg_write_bad(val, size)
 
-__prep
-int
-prep_pcibios_read_config_byte (unsigned char bus,
-			  unsigned char dev, unsigned char offset, unsigned char *val)
-{
-	unsigned char _val;                                          
-	unsigned char *ptr;
-
-	if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
-	{                   
-		*val = 0xFF;
-		return PCIBIOS_DEVICE_NOT_FOUND;    
-	} else                                                                
-	{
-		ptr = (unsigned char *)CFGPTR(dev);
-		_val = *ptr;
-	}
-	*val = _val;
-	return PCIBIOS_SUCCESSFUL;
+#define bad_byte	0xff
+#define bad_word	0xffff
+#define bad_dword	0xffffffffU
+
+#define PREP_PCI_OP(rw, size, type, op)					\
+static int __prep							\
+prep_##rw##_config_##size(struct pci_dev *dev, int offset, type val)	\
+{									\
+	if ((dev->bus->number != 0) || (DEVNO(dev->devfn) > MAX_DEVNR))	\
+	{                   						\
+		cfg_##rw##_bad(val, size)				\
+		return PCIBIOS_DEVICE_NOT_FOUND;    			\
+	}								\
+	cfg_##rw(val, CFGPTR(dev->devfn), type, op);			\
+	return PCIBIOS_SUCCESSFUL;					\
 }
 
-__prep
-int
-prep_pcibios_write_config_dword (unsigned char bus,
-			    unsigned char dev, unsigned char offset, unsigned int val)
-{
-	unsigned long _val;
-	unsigned long *ptr;
-
-	_val = le32_to_cpu(val);
-	if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
-	{
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	} else
-	{
-		ptr = (unsigned long *)CFGPTR(dev);
-		*ptr = _val;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__prep
-int
-prep_pcibios_write_config_word (unsigned char bus,
-			   unsigned char dev, unsigned char offset, unsigned short val)
-{
-	unsigned short _val;
-	unsigned short *ptr;
-
-	_val = le16_to_cpu(val);
-	if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
-	{
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	} else
-	{
-		ptr = (unsigned short *)CFGPTR(dev);
-		*ptr = _val;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-__prep
-int
-prep_pcibios_write_config_byte (unsigned char bus,
-			   unsigned char dev, unsigned char offset, unsigned char val)
-{
-	unsigned char _val;
-	unsigned char *ptr;
-
-	_val = val;
-	if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
-	{
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	} else
-	{
-		ptr = (unsigned char *)CFGPTR(dev);
-		*ptr = _val;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
+PREP_PCI_OP(read, byte, u8 *, in_8)
+PREP_PCI_OP(read, word, u16 *, in_le16)
+PREP_PCI_OP(read, dword, u32 *, in_le32)
+PREP_PCI_OP(write, byte, u8, out_8)
+PREP_PCI_OP(write, word, u16, out_le16)
+PREP_PCI_OP(write, dword, u32, out_le32)
+
+static struct pci_ops prep_pci_ops =
+{
+	prep_read_config_byte,
+	prep_read_config_word,
+	prep_read_config_dword,
+	prep_write_config_byte,
+	prep_write_config_word,
+	prep_write_config_dword
+};
 
 #define MOTOROLA_CPUTYPE_REG	0x800
 #define MOTOROLA_BASETYPE_REG	0x803
@@ -685,7 +600,8 @@
 #define MOT_HAWK_PRESENT	0x2
 
 int prep_keybd_present = 1;
-int MotMPIC = 0;
+int MotMPIC;
+int mot_multi;
 
 int __init raven_init(void)
 {
@@ -695,18 +611,18 @@
 
 	/* Check to see if the Raven chip exists. */
 	if ( _prep_type != _PREP_Motorola) {
-		OpenPIC = NULL;
+		OpenPIC_Addr = NULL;
 		return 0;
 	}
 
 	/* Check to see if this board is a type that might have a Raven. */
 	if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) {
-		OpenPIC = NULL;
+		OpenPIC_Addr = NULL;
 		return 0;
 	}
 
 	/* Check the first PCI device to see if it is a Raven. */
-	pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &devid);
+	early_read_config_dword(0, 0, 0, PCI_VENDOR_ID, &devid);
 
 	switch (devid & 0xffff0000) {
 	case MPIC_RAVEN_ID:
@@ -716,33 +632,37 @@
 		MotMPIC = MOT_HAWK_PRESENT;
 		break;
 	default:
-		OpenPIC = NULL;
+		OpenPIC_Addr = NULL;
 		return 0;
 	}
 
 
 	/* Read the memory base register. */
-	pcibios_read_config_dword(0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+	early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
 
 	if (pci_membase == 0) {
-		OpenPIC = NULL;
+		OpenPIC_Addr = NULL;
 		return 0;
 	}
 
 	/* Map the Raven MPIC registers to virtual memory. */
-	OpenPIC = (struct OpenPIC *)ioremap(pci_membase+0xC0000000, 0x22000);
+	OpenPIC_Addr = ioremap(pci_membase+0xC0000000, 0x22000);
 
 	OpenPIC_InitSenses = mvme2600_openpic_initsenses;
 	OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses);
 
-	ppc_md.get_irq = chrp_get_irq;
-	ppc_md.post_irq = chrp_post_irq;
+	ppc_md.get_irq = openpic_get_irq;
 	
 	/* If raven is present on Motorola store the system config register
 	 * for later use.
 	 */
 	ProcInfo = (unsigned long *)ioremap(0xfef80400, 4);
 
+	/* Indicate to system if this is a multiprocessor board */
+	if (!(*ProcInfo & MOT_PROC2_BIT)) {
+		mot_multi = 1;
+	}
+
 	/* This is a hack.  If this is a 2300 or 2400 mot board then there is
 	 * no keyboard controller and we have to indicate that.
 	 */
@@ -898,72 +818,8 @@
 		outb(pl_id|CAROLINA_IRQ_EDGE_MASK_HI, 0x04d1);
 		pl_id=inb(0x04d1);
 		/*printk("Hi mask now %#0x\n", pl_id);*/
-	} else if ( _prep_type == _PREP_Radstone )
-	{
-		unsigned char ucElcrM, ucElcrS;
-
-		/*
-		 * Set up edge/level
-		 */
-		switch(ucSystemType)
-		{
-			case RS_SYS_TYPE_PPC1:
-			{
-				if(ucBoardRevMaj<5)
-				{
-					ucElcrS=ELCRS_INT15_LVL;
-				}
-				else
-				{
-					ucElcrS=ELCRS_INT9_LVL |
-					        ELCRS_INT11_LVL |
-					        ELCRS_INT14_LVL |
-					        ELCRS_INT15_LVL;
-				}
-				ucElcrM=ELCRM_INT5_LVL | ELCRM_INT7_LVL;
-				break;
-			}
-
-			case RS_SYS_TYPE_PPC1a:
-			{
-				ucElcrS=ELCRS_INT9_LVL |
-				        ELCRS_INT11_LVL |
-				        ELCRS_INT14_LVL |
-				        ELCRS_INT15_LVL;
-				ucElcrM=ELCRM_INT5_LVL;
-				break;
-			}
-
-			case RS_SYS_TYPE_PPC2:
-			case RS_SYS_TYPE_PPC2a:
-			case RS_SYS_TYPE_PPC2ep:
-			case RS_SYS_TYPE_PPC4:
-			case RS_SYS_TYPE_PPC4a:
-			default:
-			{
-				ucElcrS=ELCRS_INT9_LVL |
-				        ELCRS_INT10_LVL |
-				        ELCRS_INT11_LVL |
-				        ELCRS_INT14_LVL |
-				        ELCRS_INT15_LVL;
-				ucElcrM=ELCRM_INT5_LVL |
-				        ELCRM_INT7_LVL;
-				break;
-			}
-		}
-
-		/*
-		 * Write edge/level selection
-		 */
-		outb(ucElcrS, ISA8259_S_ELCR);
-		outb(ucElcrM, ISA8259_M_ELCR);
-
-		/*
-		 * Radstone boards have PCI interrupts all set up
-		 * so leave well alone
-		 */
-		return 0;
-	} else
+	}
+	else
 	{
 		printk("No known machine pci routing!\n");
 		return -1;
@@ -987,16 +843,10 @@
         extern unsigned char *Motherboard_routes;
         unsigned char i;
 
-        if ( _prep_type == _PREP_Radstone )
-        {
-                printk("Radstone boards require no PCI fixups\n");
-		return;
-        }
-
 	prep_route_pci_interrupts();
 
 	printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
-	if (OpenPIC) {
+	if (OpenPIC_Addr) {
 		/* PCI interrupts are controlled by the OpenPIC */
 		pci_for_each_dev(dev) {
 			if (dev->bus->number == 0) {
@@ -1018,7 +868,12 @@
 
 		for ( i = 0 ; i <= 5 ; i++ )
 		{
-		        if ( dev->resource[i].start > 0x10000000 )
+			/*
+			 * Relocate PCI I/O resources if necessary so the
+			 * standard 256MB BAT covers them.
+			 */
+			if ( (pci_resource_flags(dev, i) & IORESOURCE_IO) &&
+				(dev->resource[i].start > 0x10000000) ) 
 		        {
 		                printk("Relocating PCI address %lx -> %lx\n",
 		                       dev->resource[i].start,
@@ -1029,6 +884,8 @@
 		                pci_write_config_dword(dev,
 		                        PCI_BASE_ADDRESS_0+(i*0x4),
 		                       dev->resource[i].start );
+				dev->resource[i].end =
+					(dev->resource[i].end & 0x00FFFFFF) | 0x01000000;
 		        }
 		}
 #if 0
@@ -1043,49 +900,50 @@
 	}
 }
 
-decl_config_access_method(indirect);
-
 void __init
-prep_setup_pci_ptrs(void)
+prep_find_bridges(void)
 {
-	PPC_DEVICE *hostbridge;
+	struct pci_controller* hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
 
-        printk("PReP architecture\n");
-        if ( _prep_type == _PREP_Radstone )
-        {
-		pci_config_address = (unsigned *)0x80000cf8;
-		pci_config_data = (char *)0x80000cfc;
-		set_config_access_method(indirect);		
-        }
-        else
-        {
-                hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
-		       BridgeController, PCIBridge, -1, 0);
-                if (hostbridge &&
-                    hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
-                        PnP_TAG_PACKET * pkt;
-                        set_config_access_method(indirect);
-                        pkt = PnP_find_large_vendor_packet(
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	hose->pci_mem_offset = PREP_ISA_MEM_BASE;
+	
+	printk("PReP architecture\n");
+	{
+#ifdef CONFIG_PREP_RESIDUAL	  
+		PPC_DEVICE *hostbridge;
+
+		hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
+			BridgeController, PCIBridge, -1, 0);
+		if (hostbridge &&
+			hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
+			PnP_TAG_PACKET * pkt;
+			pkt = PnP_find_large_vendor_packet(
 				res->DevicePnPHeap+hostbridge->AllocatedOffset,
 				3, 0);
-                        if(pkt)
+			if(pkt)
 			{
 #define p pkt->L4_Pack.L4_Data.L4_PPCPack
-                                pci_config_address= (unsigned *)ld_le32((unsigned *) p.PPCData);
-				pci_config_data= (unsigned char *)ld_le32((unsigned *) (p.PPCData+8));
-                        }
+				setup_indirect_pci(hose, 
+					ld_le32((unsigned *) (p.PPCData)),
+					ld_le32((unsigned *) (p.PPCData+8)));
+			}
 			else
 			{
-                                pci_config_address= (unsigned *) 0x80000cf8;
-                                pci_config_data= (unsigned char *) 0x80000cfc;
-                        }
-                }
+				setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
+			}
+		}
 		else
+#endif /* CONFIG_PREP_RESIDUAL */
 		{
-                        set_config_access_method(prep);
-                }
-
-        }
+			hose->ops = &prep_pci_ops;
+		}
+	}
 
 	ppc_md.pcibios_fixup = prep_pcibios_fixup;
 }
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.4.0/linux/arch/ppc/kernel/prep_setup.c	Sun Oct  8 09:33:07 2000
+++ linux/arch/ppc/kernel/prep_setup.c	Mon Jan 22 15:41:15 2001
@@ -32,7 +32,6 @@
 #include <linux/console.h>
 #include <linux/timex.h>
 #include <linux/pci.h>
-#include <linux/openpic.h>
 #include <linux/ide.h>
 
 #include <asm/init.h>
@@ -48,8 +47,9 @@
 #include <asm/prep_nvram.h>
 #include <asm/raven.h>
 #include <asm/keyboard.h>
-
+#include <asm/vga.h>
 #include <asm/time.h>
+
 #include "local_irq.h"
 #include "i8259.h"
 #include "open_pic.h"
@@ -84,7 +84,7 @@
 extern void pckbd_init_hw(void);
 extern unsigned char pckbd_sysrq_xlate[128];
 
-extern void prep_setup_pci_ptrs(void);
+extern void prep_find_bridges(void);
 extern char saved_command_line[256];
 
 int _prep_type;
@@ -101,23 +101,23 @@
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 extern int probingmem;
-extern unsigned long loops_per_sec;
+extern unsigned long loops_per_jiffy;
 
 #ifdef CONFIG_BLK_DEV_RAM
 extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
 extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
 extern int rd_image_start;	/* starting block # of image */
 #endif
-#ifdef CONFIG_VGA_CONSOLE
-unsigned long vgacon_remap_base;
-#endif
 
 int __prep
 prep_get_cpuinfo(char *buffer)
 {
 	extern char *Motherboard_map_name;
-	int len, i;
-  
+	int len;
+#ifdef CONFIG_PREP_RESIDUAL
+	int i;
+#endif
+
 #ifdef CONFIG_SMP
 #define CD(X)		(cpu_data[n].X)  
 #else
@@ -190,7 +190,10 @@
 	}
 	
 	
-no_l2:	
+no_l2:
+#ifndef CONFIG_PREP_RESIDUAL
+	return len;
+#else	
 	if ( res->ResidualLength == 0 )
 		return len;
 	
@@ -205,8 +208,8 @@
 				       res->Memories[i].SIMMSize);
 	}
 	len += sprintf(buffer+len,"\n");
-
 	return len;
+#endif
 }
 
 void __init
@@ -214,11 +217,16 @@
 {
 	extern char cmd_line[];
 	unsigned char reg;
+#if 0 /* unused?? */
 	unsigned char ucMothMemType;
 	unsigned char ucEquipPres1;
+#endif
 
 	/* init to some ~sane value until calibrate_delay() runs */
-	loops_per_sec = 50000000;
+	loops_per_jiffy = 50000000;
+	
+	/* Lookup PCI host bridges */
+	prep_find_bridges();
 	
 	/* Set up floppy in PS/2 mode */
 	outb(0x09, SIO_CONFIG_RA);
@@ -247,41 +255,6 @@
 		*(unsigned char *)(0x8000081c) |= 3;
 		ROOT_DEV = to_kdev_t(0x0802); /* sda2 */
 		break;
-	case _PREP_Radstone:
-		ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
-
-		/*
-		 * Determine system type
-		 */
-		ucMothMemType=inb(0x866);
-		ucEquipPres1=inb(0x80c);
-
-		ucSystemType=((ucMothMemType&0x03)<<1) |
-			     ((ucEquipPres1&0x80)>>7);
-		ucSystemType^=7;
-
-		/*
-		 * Determine board revision for use by
-		 * rev. specific code
-		 */
-		ucBoardRev=inb(0x854);
-		ucBoardRevMaj=ucBoardRev>>5;
-		ucBoardRevMin=ucBoardRev&0x1f;
-
-		/*
-		 * Most Radstone boards have memory mapped NvRAM
-		 */
-		if((ucSystemType==RS_SYS_TYPE_PPC1) && (ucBoardRevMaj<5))
-		{
-			ppc_md.nvram_read_val = prep_nvram_read_val;
-			ppc_md.nvram_write_val = prep_nvram_write_val;
-		}
-		else
-		{
-			ppc_md.nvram_read_val = rs_nvram_read_val;
-			ppc_md.nvram_write_val = rs_nvram_write_val;
-		}
-		break;
 	}
 
       /* Read in NVRAM data */ 
@@ -341,12 +314,6 @@
 #endif /* CONFIG_SOUND_CS4232 */	
 
 	/*print_residual_device_info();*/
-        request_region(0x20,0x20,"pic1");
-	request_region(0xa0,0x20,"pic2");
-	request_region(0x00,0x20,"dma1");
-	request_region(0x40,0x20,"timer");
-	request_region(0x80,0x10,"dma page reg");
-	request_region(0xc0,0x20,"dma2");
 
 	raven_init();
 
@@ -365,6 +332,7 @@
  */
 void __init prep_res_calibrate_decr(void)
 {
+#ifdef CONFIG_PREP_RESIDUAL	
 	unsigned long freq, divisor=4;
 
 	freq = res->VitalProductData.ProcessorBusHz;
@@ -372,6 +340,7 @@
 	       (freq/divisor)/1000000, (freq/divisor)%1000000);
 	tb_ticks_per_jiffy = freq / HZ / divisor;
 	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+#endif	
 }
 
 /*
@@ -585,15 +554,16 @@
 {
         int len = 0;
 
-
 	/* PREP's without residual data will give incorrect values here */
 	len += sprintf(len+buffer, "clock\t\t: ");
+#ifdef CONFIG_PREP_RESIDUAL	
 	if ( res->ResidualLength )
 		len += sprintf(len+buffer, "%ldMHz\n",
 		       (res->VitalProductData.ProcessorHz > 1024) ?
 		       res->VitalProductData.ProcessorHz>>20 :
 		       res->VitalProductData.ProcessorHz);
 	else
+#endif /* CONFIG_PREP_RESIDUAL */
 		len += sprintf(len+buffer, "???\n");
 
 	return len;
@@ -640,19 +610,11 @@
 {
 	int i;
 
-	if (OpenPIC != NULL) {
-		for ( i = 16 ; i < 36 ; i++ )
-			irq_desc[i].handler = &open_pic;
-		openpic_init(1);
-	}
-	
-        for ( i = 0 ; i < 16  ; i++ )
+	if (OpenPIC_Addr != NULL)
+		openpic_init(1, NUM_8259_INTERRUPTS, 0, -1);
+        for ( i = 0 ; i < NUM_8259_INTERRUPTS  ; i++ )
                 irq_desc[i].handler = &i8259_pic;
-        i8259_init();
-#ifdef CONFIG_SMP
-	request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action,
-		    0, "IPI0", 0);
-#endif /* CONFIG_SMP */
+        i8259_init();	
 }
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
@@ -708,19 +670,14 @@
 			unsigned int extent,
 			const char *name)
 {
-        request_region(from, extent, name);
+	request_region(from, extent, name);
 }
 
 void __prep
 prep_ide_release_region(ide_ioreg_t from,
 			unsigned int extent)
 {
-        release_region(from, extent);
-}
-
-void __prep
-prep_ide_fix_driveid(struct hd_driveid *id)
-{
+	release_region(from, extent);
 }
 
 void __init
@@ -743,17 +700,52 @@
 }
 #endif
 
+unsigned long *MotSave_SmpIar;
+unsigned char *MotSave_CpusState[2];
+
+void __init
+prep_init2(void)
+{
+#ifdef CONFIG_NVRAM  
+	request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+#endif
+	request_region(0x20,0x20,"pic1");
+	request_region(0xa0,0x20,"pic2");
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
+}
+
 void __init
 prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	  unsigned long r6, unsigned long r7)
 {
+#ifdef CONFIG_PREP_RESIDUAL	
+	RESIDUAL *old_res = (RESIDUAL *)(r3 + KERNELBASE);
+
 	/* make a copy of residual data */
 	if ( r3 )
 	{
 		memcpy((void *)res,(void *)(r3+KERNELBASE),
 		       sizeof(RESIDUAL));
+
+		/* These need to be saved for the Motorola Prep 
+		 * MVME4600 and Dual MTX boards.
+		 */
+		MotSave_SmpIar = &old_res->VitalProductData.SmpIar;
+		MotSave_CpusState[0] = &old_res->Cpus[0].CpuState;
+		MotSave_CpusState[1] = &old_res->Cpus[1].CpuState;
 	}
+#endif
 
+	/* Copy cmd_line parameters */
+	if ( r6)
+	{
+		*(char *)(r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+	}
+	
 	isa_io_base = PREP_ISA_IO_BASE;
 	isa_mem_base = PREP_ISA_MEM_BASE;
 	pci_dram_offset = PREP_PCI_DRAM_OFFSET;
@@ -762,29 +754,19 @@
 	DMA_MODE_WRITE = 0x48;
 
 	/* figure out what kind of prep workstation we are */
+#ifdef CONFIG_PREP_RESIDUAL	
 	if ( res->ResidualLength != 0 )
 	{
 		if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
 			_prep_type = _PREP_IBM;
-                else if (!strncmp(res->VitalProductData.PrintableModel,
-                                  "Radstone",8))
-                {
-                        extern char *Motherboard_map_name;
-
-                        _prep_type = _PREP_Radstone;
-                        Motherboard_map_name=
-                                res->VitalProductData.PrintableModel;
-                }
-		else
-			_prep_type = _PREP_Motorola;
+		_prep_type = _PREP_Motorola;
 	}
 	else /* assume motorola if no residual (netboot?) */
+#endif	  
 	{
 		_prep_type = _PREP_Motorola;
 	}
 
-	prep_setup_pci_ptrs();
-
 	ppc_md.setup_arch     = prep_setup_arch;
 	ppc_md.setup_residual = prep_setup_residual;
 	ppc_md.get_cpuinfo    = prep_get_cpuinfo;
@@ -792,40 +774,14 @@
 	ppc_md.init_IRQ       = prep_init_IRQ;
 	/* this gets changed later on if we have an OpenPIC -- Cort */
 	ppc_md.get_irq        = prep_get_irq;
-	ppc_md.init           = NULL;
+	ppc_md.init           = prep_init2;
 
 	ppc_md.restart        = prep_restart;
 	ppc_md.power_off      = prep_power_off;
 	ppc_md.halt           = prep_halt;
 
 	ppc_md.time_init      = NULL;
-	if (_prep_type == _PREP_Radstone) {
-		/*
-		 * We require a direct restart as port 92 does not work on
-		 * all Radstone boards
-		 */
-		ppc_md.restart        = prep_direct_restart;
-		/*
-		 * The RTC device used varies according to board type
-		 */
-		if(((ucSystemType==RS_SYS_TYPE_PPC1) && (ucBoardRevMaj>=5)) ||
-		   (ucSystemType==RS_SYS_TYPE_PPC1a))
-		{
-			ppc_md.set_rtc_time   = mk48t59_set_rtc_time;
-			ppc_md.get_rtc_time   = mk48t59_get_rtc_time;
-			ppc_md.time_init      = mk48t59_init;
-		}
-		else
-		{
-			ppc_md.set_rtc_time   = mc146818_set_rtc_time;
-			ppc_md.get_rtc_time   = mc146818_get_rtc_time;
-		}
-		/*
-		 * Determine the decrementer rate from the residual data
-		 */
-		ppc_md.calibrate_decr = prep_res_calibrate_decr;
-	}
-	else if (_prep_type == _PREP_IBM) {
+	if (_prep_type == _PREP_IBM) {
 		ppc_md.set_rtc_time   = mc146818_set_rtc_time;
 		ppc_md.get_rtc_time   = mc146818_get_rtc_time;
 		ppc_md.calibrate_decr = prep_calibrate_decr;
@@ -845,7 +801,7 @@
         ppc_ide_md.ide_check_region = prep_ide_check_region;
         ppc_ide_md.ide_request_region = prep_ide_request_region;
         ppc_ide_md.ide_release_region = prep_ide_release_region;
-        ppc_ide_md.fix_driveid = prep_ide_fix_driveid;
+        ppc_ide_md.fix_driveid = NULL;
         ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports;
 #endif		
         ppc_ide_md.io_base = _IO_BASE;
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/proc_rtas.c linux/arch/ppc/kernel/proc_rtas.c
--- v2.4.0/linux/arch/ppc/kernel/proc_rtas.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/proc_rtas.c	Mon Jan 22 15:41:15 2001
@@ -0,0 +1,784 @@
+/*
+ *   arch/ppc/kernel/proc_rtas.c
+ *   Copyright (C) 2000 Tilmann Bitterberg
+ *   (tilmann@bitterberg.de)
+ *
+ *   RTAS (Runtime Abstraction Services) stuff
+ *   Intention is to provide a clean user interface
+ *   to use the RTAS.
+ *
+ *   TODO:
+ *   Split off a header file and maybe move it to a different
+ *   location. Write Documentation on what the /proc/rtas/ entries
+ *   actually do.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/ctype.h>
+#include <linux/time.h>
+#include <linux/string.h>
+
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h> /* for ppc_md */
+#include <asm/time.h>
+
+/* Token for Sensors */
+#define KEY_SWITCH		0x0001
+#define ENCLOSURE_SWITCH	0x0002
+#define THERMAL_SENSOR		0x0003
+#define LID_STATUS		0x0004
+#define POWER_SOURCE		0x0005
+#define BATTERY_VOLTAGE		0x0006
+#define BATTERY_REMAINING	0x0007
+#define BATTERY_PERCENTAGE	0x0008
+#define EPOW_SENSOR		0x0009
+#define BATTERY_CYCLESTATE	0x000a
+#define BATTERY_CHARGING	0x000b
+
+/* IBM specific sensors */
+#define IBM_SURVEILLANCE	0x2328 /* 9000 */
+#define IBM_FANRPM		0x2329 /* 9001 */
+#define IBM_VOLTAGE		0x232a /* 9002 */
+#define IBM_DRCONNECTOR		0x232b /* 9003 */
+#define IBM_POWERSUPPLY		0x232c /* 9004 */
+#define IBM_INTQUEUE		0x232d /* 9005 */
+
+/* Status return values */
+#define SENSOR_CRITICAL_HIGH	13
+#define SENSOR_WARNING_HIGH	12
+#define SENSOR_NORMAL		11
+#define SENSOR_WARNING_LOW	10
+#define SENSOR_CRITICAL_LOW	 9
+#define SENSOR_SUCCESS		 0
+#define SENSOR_HW_ERROR		-1
+#define SENSOR_BUSY		-2
+#define SENSOR_NOT_EXIST	-3
+#define SENSOR_DR_ENTITY	-9000
+
+/* Location Codes */
+#define LOC_SCSI_DEV_ADDR	'A'
+#define LOC_SCSI_DEV_LOC	'B'
+#define LOC_CPU			'C'
+#define LOC_DISKETTE		'D'
+#define LOC_ETHERNET		'E'
+#define LOC_FAN			'F'
+#define LOC_GRAPHICS		'G'
+/* reserved / not used		'H' */
+#define LOC_IO_ADAPTER		'I'
+/* reserved / not used		'J' */
+#define LOC_KEYBOARD		'K'
+#define LOC_LCD			'L'
+#define LOC_MEMORY		'M'
+#define LOC_NV_MEMORY		'N'
+#define LOC_MOUSE		'O'
+#define LOC_PLANAR		'P'
+#define LOC_OTHER_IO		'Q'
+#define LOC_PARALLEL		'R'
+#define LOC_SERIAL		'S'
+#define LOC_DEAD_RING		'T'
+#define LOC_RACKMOUNTED		'U' /* for _u_nit is rack mounted */
+#define LOC_VOLTAGE		'V'
+#define LOC_SWITCH_ADAPTER	'W'
+#define LOC_OTHER		'X'
+#define LOC_FIRMWARE		'Y'
+#define LOC_SCSI		'Z'
+
+/* Tokens for indicators */
+#define TONE_FREQUENCY		0x0001 /* 0 - 1000 (HZ)*/
+#define TONE_VOLUME		0x0002 /* 0 - 100 (%) */
+#define SYSTEM_POWER_STATE	0x0003 
+#define WARNING_LIGHT		0x0004
+#define DISK_ACTIVITY_LIGHT	0x0005
+#define HEX_DISPLAY_UNIT	0x0006
+#define BATTERY_WARNING_TIME	0x0007
+#define CONDITION_CYCLE_REQUEST	0x0008
+#define SURVEILLANCE_INDICATOR	0x2328 /* 9000 */
+#define DR_ACTION		0x2329 /* 9001 */
+#define DR_INDICATOR		0x232a /* 9002 */
+/* 9003 - 9004: Vendor specific */
+#define GLOBAL_INTERRUPT_QUEUE	0x232d /* 9005 */
+/* 9006 - 9999: Vendor specific */
+
+/* other */
+#define MAX_SENSORS		 17  /* I only know of 17 sensors */    
+#define MAX_LINELENGTH          256
+#define SENSOR_PREFIX		"ibm,sensor-"
+#define cel_to_fahr(x)		((x*9/5)+32)
+
+
+/* Globals */
+static struct proc_dir_entry *proc_rtas;
+static struct rtas_sensors sensors;
+static struct device_node *rtas;
+static unsigned long power_on_time = 0; /* Save the time the user set */
+static char progress_led[MAX_LINELENGTH];
+
+static unsigned long rtas_tone_frequency = 1000;
+static unsigned long rtas_tone_volume = 0;
+
+/* ****************STRUCTS******************************************* */
+struct individual_sensor {
+	unsigned int token;
+	unsigned int quant;
+};
+
+struct rtas_sensors {
+        struct individual_sensor sensor[MAX_SENSORS];
+	unsigned int quant;
+};
+
+/* ****************************************************************** */
+/* Declarations */
+static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
+		int count, int *eof, void *data);
+static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, 
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, 
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos);
+
+static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos);
+
+struct file_operations ppc_rtas_poweron_operations = {
+	read:		ppc_rtas_poweron_read,
+	write:		ppc_rtas_poweron_write
+};
+struct file_operations ppc_rtas_progress_operations = {
+	read:		ppc_rtas_progress_read,
+	write:		ppc_rtas_progress_write
+};
+
+struct file_operations ppc_rtas_clock_operations = {
+	read:		ppc_rtas_clock_read,
+	write:		ppc_rtas_clock_write
+};
+
+struct file_operations ppc_rtas_tone_freq_operations = {
+	read:		ppc_rtas_tone_freq_read,
+	write:		ppc_rtas_tone_freq_write
+};
+struct file_operations ppc_rtas_tone_volume_operations = {
+	read:		ppc_rtas_tone_volume_read,
+	write:		ppc_rtas_tone_volume_write
+};
+
+int ppc_rtas_find_all_sensors (void);
+int ppc_rtas_process_sensor(struct individual_sensor s, int state, 
+		int error, char * buf);
+char * ppc_rtas_process_error(int error);
+int get_location_code(struct individual_sensor s, char * buf);
+int check_location_string (char *c, char * buf);
+int check_location (char *c, int idx, char * buf);
+
+/* ****************************************************************** */
+/* MAIN                                                               */
+/* ****************************************************************** */
+void proc_rtas_init(void)
+{
+	struct proc_dir_entry *entry;
+
+	rtas = find_devices("rtas");
+	if ((rtas == 0) || (_machine != _MACH_chrp)) {
+		return;
+	}
+	
+	proc_rtas = proc_mkdir("rtas", 0);
+	if (proc_rtas == 0)
+		return;
+
+	/* /proc/rtas entries */
+
+	entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_rtas);
+	if (entry) entry->proc_fops = &ppc_rtas_progress_operations;
+
+	entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_rtas); 
+	if (entry) entry->proc_fops = &ppc_rtas_clock_operations;
+
+	entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_rtas); 
+	if (entry) entry->proc_fops = &ppc_rtas_poweron_operations;
+
+	create_proc_read_entry("sensors", S_IRUGO, proc_rtas, 
+			ppc_rtas_sensor_read, NULL);
+	
+	entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_rtas); 
+	if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations;
+
+	entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas); 
+	if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations;
+}
+
+/* ****************************************************************** */
+/* POWER-ON-TIME                                                      */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos)
+{
+	struct rtc_time tm;
+	unsigned long nowtime;
+	char *dest;
+	int error;
+
+	nowtime = simple_strtoul(buf, &dest, 10);
+	if (*dest != '\0' && *dest != '\n') {
+		printk("ppc_rtas_poweron_write: Invalid time\n");
+		return count;
+	}
+	power_on_time = nowtime; /* save the time */
+
+	to_tm(nowtime, &tm);
+
+	error = call_rtas("set-time-for-power-on", 7, 1, NULL, 
+			tm.tm_year, tm.tm_mon, tm.tm_mday, 
+			tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
+	if (error != 0)
+		printk(KERN_WARNING "error: setting poweron time returned: %s\n", 
+				ppc_rtas_process_error(error));
+	return count;
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos)
+{
+	int n;
+	if (power_on_time == 0)
+		n = sprintf(buf, "Power on time not set\n");
+	else
+		n = sprintf(buf, "%lu\n", power_on_time);
+
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
+
+/* ****************************************************************** */
+/* PROGRESS                                                           */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos)
+{
+	unsigned long hex;
+
+	strcpy(progress_led, buf); /* save the string */
+	/* Lets see if the user passed hexdigits */
+	hex = simple_strtoul(buf, NULL, 10);
+	
+	ppc_md.progress ((char *)buf, hex);
+	return count;
+
+	/* clear the line */ /* ppc_md.progress("                   ", 0xffff);*/
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos)
+{
+	int n = 0;
+	if (progress_led != NULL)
+		n = sprintf (buf, "%s\n", progress_led);
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
+
+/* ****************************************************************** */
+/* CLOCK                                                              */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, 
+		size_t count, loff_t *ppos)
+{
+	struct rtc_time tm;
+	unsigned long nowtime;
+	char *dest;
+	int error;
+
+	nowtime = simple_strtoul(buf, &dest, 10);
+	if (*dest != '\0' && *dest != '\n') {
+		printk("ppc_rtas_clock_write: Invalid time\n");
+		return count;
+	}
+
+	to_tm(nowtime, &tm);
+	error = call_rtas("set-time-of-day", 7, 1, NULL, 
+			tm.tm_year, tm.tm_mon, tm.tm_mday, 
+			tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
+	if (error != 0)
+		printk(KERN_WARNING "error: setting the clock returned: %s\n", 
+				ppc_rtas_process_error(error));
+	return count;
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, 
+		size_t count, loff_t *ppos)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned long *ret = kmalloc(4*8, GFP_KERNEL);
+	int n, error;
+
+	error = call_rtas("get-time-of-day", 0, 8, ret);
+	
+	year = ret[0]; mon  = ret[1]; day  = ret[2];
+	hour = ret[3]; min  = ret[4]; sec  = ret[5];
+
+	if (error != 0){
+		printk(KERN_WARNING "error: reading the clock returned: %s\n", 
+				ppc_rtas_process_error(error));
+		n = sprintf (buf, "0");
+	} else { 
+		n = sprintf (buf, "%lu\n", mktime(year, mon, day, hour, min, sec));
+	}
+	kfree(ret);
+
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
+
+/* ****************************************************************** */
+/* SENSOR STUFF                                                       */
+/* ****************************************************************** */
+static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
+		int count, int *eof, void *data)
+{
+	int i,j,n;
+	unsigned long ret;
+	int state, error;
+	char buffer[MAX_LINELENGTH*MAX_SENSORS]; /* May not be enough */
+
+	if (count < 0)
+		return -EINVAL;
+
+	n  = sprintf ( buffer  , "RTAS (RunTime Abstraction Services) Sensor Information\n");
+	n += sprintf ( buffer+n, "Sensor\t\tValue\t\tCondition\tLocation\n");
+	n += sprintf ( buffer+n, "********************************************************\n");
+
+	if (ppc_rtas_find_all_sensors() != 0) {
+		n += sprintf ( buffer+n, "\nNo sensors are available\n");
+		goto return_string;
+	}
+
+	for (i=0; i<sensors.quant; i++) {
+		j = sensors.sensor[i].quant;
+		/* A sensor may have multiple instances */
+		while (j >= 0) {
+			error =	call_rtas("get-sensor-state", 2, 2, &ret, 
+				  sensors.sensor[i].token, sensors.sensor[i].quant-j);
+			state = (int) ret;
+			n += ppc_rtas_process_sensor(sensors.sensor[i], state, error, buffer+n );
+			n += sprintf (buffer+n, "\n");
+			j--;
+		} /* while */
+	} /* for */
+
+return_string:
+	if (off >= strlen(buffer)) {
+		*eof = 1;
+		return 0;
+	}
+	if (n > strlen(buffer) - off)
+		n = strlen(buffer) - off;
+	if (n > count)
+		n = count;
+	else
+		*eof = 1;
+	memcpy(buf, buffer + off, n);
+	*start = buf;
+	return n;
+}
+
+/* ****************************************************************** */
+
+int ppc_rtas_find_all_sensors (void)
+{
+	unsigned long *utmp;
+	int len, i, j;
+
+	utmp = (unsigned long *) get_property(rtas, "rtas-sensors", &len);
+	if (utmp == NULL) {
+		printk (KERN_ERR "error: could not get rtas-sensors\n");
+		return 1;
+	}
+
+	sensors.quant = len / 8;      /* int + int */
+
+	for (i=0, j=0; j<sensors.quant; i+=2, j++) {
+		sensors.sensor[j].token = utmp[i];
+		sensors.sensor[j].quant = utmp[i+1];
+	}
+	return 0;
+}
+
+/* ****************************************************************** */
+/*
+ * Builds a string of what rtas returned
+ */
+char * ppc_rtas_process_error(int error)
+{
+	switch (error) {
+		case SENSOR_CRITICAL_HIGH:
+			return "(critical high)";
+		case SENSOR_WARNING_HIGH:
+			return "(warning high)";
+		case SENSOR_NORMAL:
+			return "(normal)";
+		case SENSOR_WARNING_LOW:
+			return "(warning low)";
+		case SENSOR_CRITICAL_LOW:
+			return "(critical low)";
+		case SENSOR_SUCCESS:
+			return "(read ok)";
+		case SENSOR_HW_ERROR:
+			return "(hardware error)";
+		case SENSOR_BUSY:
+			return "(busy)";
+		case SENSOR_NOT_EXIST:
+			return "(non existant)";
+		case SENSOR_DR_ENTITY:
+			return "(dr entity removed)";
+		default:
+			return "(UNKNOWN)";
+	}
+}
+
+/* ****************************************************************** */
+/*
+ * Builds a string out of what the sensor said
+ */
+
+int ppc_rtas_process_sensor(struct individual_sensor s, int state, 
+		int error, char * buf) 
+{
+	/* Defined return vales */
+	const char * key_switch[]        = { "Off\t", "Normal\t", "Secure\t", "Mainenance" };
+	const char * enclosure_switch[]  = { "Closed", "Open" };
+	const char * lid_status[]        = { " ", "Open", "Closed" };
+	const char * power_source[]      = { "AC\t", "Battery", "AC & Battery" };
+	const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" };
+	const char * epow_sensor[]       = { 
+		"EPOW Reset", "Cooling warning", "Power warning",
+		"System shutdown", "System halt", "EPOW main enclosure",
+		"EPOW power off" };
+	const char * battery_cyclestate[]  = { "None", "In progress", "Requested" };
+	const char * battery_charging[]    = { "Charging", "Discharching", "No current flow" };
+	const char * ibm_drconnector[]     = { "Empty", "Present" };
+	const char * ibm_intqueue[]        = { "Disabled", "Enabled" };
+
+	int have_strings = 0;
+	int temperature = 0;
+	int unknown = 0;
+	int n = 0;
+
+	/* What kind of sensor do we have here? */
+	switch (s.token) {
+		case KEY_SWITCH:
+			n += sprintf(buf+n, "Key switch:\t");
+			n += sprintf(buf+n, "%s\t", key_switch[state]);
+			have_strings = 1;
+			break;
+		case ENCLOSURE_SWITCH:
+			n += sprintf(buf+n, "Enclosure switch:\t");
+			n += sprintf(buf+n, "%s\t", enclosure_switch[state]);
+			have_strings = 1;
+			break;
+		case THERMAL_SENSOR:
+			n += sprintf(buf+n, "Temp. (°C/°F):\t");
+			temperature = 1;
+			break;
+		case LID_STATUS:
+			n += sprintf(buf+n, "Lid status:\t");
+			n += sprintf(buf+n, "%s\t", lid_status[state]);
+			have_strings = 1;
+			break;
+		case POWER_SOURCE:
+			n += sprintf(buf+n, "Power source:\t");
+			n += sprintf(buf+n, "%s\t", power_source[state]);
+			have_strings = 1;
+			break;
+		case BATTERY_VOLTAGE:
+			n += sprintf(buf+n, "Battery voltage:\t");
+			break;
+		case BATTERY_REMAINING:
+			n += sprintf(buf+n, "Battery remaining:\t");
+			n += sprintf(buf+n, "%s\t", battery_remaining[state]);
+			have_strings = 1;
+			break;
+		case BATTERY_PERCENTAGE:
+			n += sprintf(buf+n, "Battery percentage:\t");
+			break;
+		case EPOW_SENSOR:
+			n += sprintf(buf+n, "EPOW Sensor:\t");
+			n += sprintf(buf+n, "%s\t", epow_sensor[state]);
+			have_strings = 1;
+			break;
+		case BATTERY_CYCLESTATE:
+			n += sprintf(buf+n, "Battery cyclestate:\t");
+			n += sprintf(buf+n, "%s\t", battery_cyclestate[state]);
+			have_strings = 1;
+			break;
+		case BATTERY_CHARGING:
+			n += sprintf(buf+n, "Battery Charging:\t");
+			n += sprintf(buf+n, "%s\t", battery_charging[state]);
+			have_strings = 1;
+			break;
+		case IBM_SURVEILLANCE:
+			n += sprintf(buf+n, "Surveillance:\t");
+			break;
+		case IBM_FANRPM:
+			n += sprintf(buf+n, "Fan (rpm):\t");
+			break;
+		case IBM_VOLTAGE:
+			n += sprintf(buf+n, "Voltage (mv):\t");
+			break;
+		case IBM_DRCONNECTOR:
+			n += sprintf(buf+n, "DR connector:\t");
+			n += sprintf(buf+n, "%s\t", ibm_drconnector[state]);
+			have_strings = 1;
+			break;
+		case IBM_POWERSUPPLY:
+			n += sprintf(buf+n, "Powersupply:\t");
+			break;
+		case IBM_INTQUEUE:
+			n += sprintf(buf+n, "Interrupt queue:\t");
+			n += sprintf(buf+n, "%s\t", ibm_intqueue[state]);
+			have_strings = 1;
+			break;
+		default:
+			n += sprintf(buf+n,  "Unkown sensor (type %d), ignoring it\n",
+					s.token);
+			unknown = 1;
+			have_strings = 1;
+			break;
+	}
+	if (have_strings == 0) {
+		if (temperature) {
+			n += sprintf(buf+n, "%4d /%4d\t", state, cel_to_fahr(state));
+		} else
+			n += sprintf(buf+n, "%10d\t", state);
+	}
+	if (unknown == 0) {
+		n += sprintf ( buf+n, "%s\t", ppc_rtas_process_error(error));
+		n += get_location_code(s, buf+n);
+	}
+	return n;
+}
+
+/* ****************************************************************** */
+
+int check_location (char *c, int idx, char * buf)
+{
+	int n = 0;
+
+	switch (*(c+idx)) {
+		case LOC_PLANAR:
+			n += sprintf ( buf, "Planar #%c", *(c+idx+1));
+			break;
+		case LOC_CPU:
+			n += sprintf ( buf, "CPU #%c", *(c+idx+1));
+			break;
+		case LOC_FAN:
+			n += sprintf ( buf, "Fan #%c", *(c+idx+1));
+			break;
+		case LOC_RACKMOUNTED:
+			n += sprintf ( buf, "Rack #%c", *(c+idx+1));
+			break;
+		case LOC_VOLTAGE:
+			n += sprintf ( buf, "Voltage #%c", *(c+idx+1));
+			break;
+		case LOC_LCD:
+			n += sprintf ( buf, "LCD #%c", *(c+idx+1));
+			break;
+		case '.':
+			n += sprintf ( buf, "- %c", *(c+idx+1));
+		default:
+			n += sprintf ( buf, "Unknown location");
+			break;
+	}
+	return n;
+}
+
+
+/* ****************************************************************** */
+/* 
+ * Format: 
+ * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ]
+ * the '.' may be an abbrevation
+ */
+int check_location_string (char *c, char *buf)
+{
+	int n=0,i=0;
+
+	while (c[i]) {
+		if (isalpha(c[i]) || c[i] == '.') {
+			 n += check_location(c, i, buf+n);
+		}
+		else if (c[i] == '/' || c[i] == '-')
+			n += sprintf(buf+n, " at ");
+		i++;
+	}
+	return n;
+}
+
+
+/* ****************************************************************** */
+
+int get_location_code(struct individual_sensor s, char * buffer)
+{
+	char rstr[512], tmp[10], tmp2[10];
+	int n=0, i=0, llen, len;
+	/* char *buf = kmalloc(MAX_LINELENGTH, GFP_KERNEL); */
+	char *ret;
+
+	static int pos = 0; /* remember position where buffer was */
+
+	/* construct the sensor number like 0003 */
+	/* fill with zeros */
+	n = sprintf(tmp, "%d", s.token);
+	len = strlen(tmp);
+	while (strlen(tmp) < 4)
+		n += sprintf (tmp+n, "0");
+	
+	/* invert the string */
+	while (tmp[i]) {
+		if (i<len)
+			tmp2[4-len+i] = tmp[i];
+		else
+			tmp2[3-i] = tmp[i];
+		i++;
+	}
+	tmp2[4] = '\0';
+
+	sprintf (rstr, SENSOR_PREFIX"%s", tmp2);
+
+	ret = (char *) get_property(rtas, rstr, &llen);
+
+	n=0;
+	if (ret[0] == '\0')
+		n += sprintf ( buffer+n, "--- ");/* does not have a location */
+	else {
+		char t[50];
+		ret += pos;
+
+		n += check_location_string(ret, buffer + n);
+		n += sprintf ( buffer+n, " ");
+		/* see how many characters we have printed */
+		sprintf ( t, "%s ", ret);
+
+		pos += strlen(t);
+		if (pos >= llen) pos=0;
+	}
+	return n;
+}
+/* ****************************************************************** */
+/* INDICATORS - Tone Frequency                                        */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos)
+{
+	unsigned long freq;
+	char *dest;
+	int error;
+	freq = simple_strtoul(buf, &dest, 10);
+	if (*dest != '\0' && *dest != '\n') {
+		printk("ppc_rtas_tone_freq_write: Invalid tone freqency\n");
+		return count;
+	}
+	if (freq < 0) freq = 0;
+	rtas_tone_frequency = freq; /* save it for later */
+	error = call_rtas("set-indicator", 3, 1, NULL,
+			TONE_FREQUENCY, 0, freq);
+	if (error != 0)
+		printk(KERN_WARNING "error: setting tone frequency returned: %s\n", 
+				ppc_rtas_process_error(error));
+	return count;
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos)
+{
+	int n;
+	n = sprintf(buf, "%lu\n", rtas_tone_frequency);
+
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
+/* ****************************************************************** */
+/* INDICATORS - Tone Volume                                           */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos)
+{
+	unsigned long volume;
+	char *dest;
+	int error;
+	volume = simple_strtoul(buf, &dest, 10);
+	if (*dest != '\0' && *dest != '\n') {
+		printk("ppc_rtas_tone_volume_write: Invalid tone volume\n");
+		return count;
+	}
+	if (volume < 0) volume = 0;
+	if (volume > 100) volume = 100;
+	
+        rtas_tone_volume = volume; /* save it for later */
+	error = call_rtas("set-indicator", 3, 1, NULL,
+			TONE_VOLUME, 0, volume);
+	if (error != 0)
+		printk(KERN_WARNING "error: setting tone volume returned: %s\n", 
+				ppc_rtas_process_error(error));
+	return count;
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos)
+{
+	int n;
+	n = sprintf(buf, "%lu\n", rtas_tone_volume);
+
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.4.0/linux/arch/ppc/kernel/process.c	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/kernel/process.c	Mon Jan 22 15:41:15 2001
@@ -222,16 +222,17 @@
 		giveup_fpu(prev);
 #ifdef CONFIG_ALTIVEC	
 	/*
-	 * If the previous thread 1) has some altivec regs it wants saved
-	 * (has bits in vrsave set) and 2) used altivec in the last quantum
+	 * If the previous thread used altivec in the last quantum
 	 * (thus changing altivec regs) then save them.
+	 * We used to check the VRSAVE register but not all apps
+	 * set it, so we don't rely on it now (and in fact we need
+	 * to save & restore VSCR even if VRSAVE == 0).  -- paulus
 	 *
 	 * On SMP we always save/restore altivec regs just to avoid the
 	 * complexity of changing processors.
 	 *  -- Cort
 	 */
-	if ( (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) &&
-	     prev->thread.vrsave )
+	if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)))
 		giveup_altivec(prev);
 #endif /* CONFIG_ALTIVEC */	
 	current_set[smp_processor_id()] = new;
@@ -251,13 +252,15 @@
 {
 	int i;
 
-	printk("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx\n",
-	       regs->nip, regs->xer, regs->link, regs,regs->trap);
+	printk("NIP: %08lX XER: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx\n",
+	       regs->nip, regs->xer, regs->link, regs->gpr[1], regs,regs->trap);
 	printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
 	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
 	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
 	       regs->msr&MSR_IR ? 1 : 0,
 	       regs->msr&MSR_DR ? 1 : 0);
+	if (regs->trap == 0x300 || regs->trap == 0x600)
+		printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr);
 	printk("TASK = %p[%d] '%s' ",
 	       current, current->pid, current->comm);
 	printk("Last syscall: %ld ", current->thread.last_syscall);
@@ -285,7 +288,7 @@
 			printk("\n");
 		}
 	}
-out:
+out: ;
 }
 
 void exit_thread(void)
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.4.0/linux/arch/ppc/kernel/prom.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/prom.c	Mon Jan 22 15:41:15 2001
@@ -28,10 +28,11 @@
 #include <asm/smp.h>
 #include <asm/bootx.h>
 #include <asm/system.h>
-#include <asm/gemini.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/bitops.h>
+/* for openpic_to_irq */
+#include "open_pic.h"
 
 #ifdef CONFIG_FB
 #include <asm/linux_logo.h>
@@ -95,26 +96,28 @@
 #define FB_MAX	8
 #endif
 char *prom_display_paths[FB_MAX] __initdata = { 0, };
-unsigned int prom_num_displays = 0;
-char *of_stdout_device = 0;
-
-prom_entry prom = 0;
-ihandle prom_chosen = 0, prom_stdout = 0, prom_disp_node = 0;
+unsigned int prom_num_displays __initdata = 0;
+char *of_stdout_device __initdata = 0;
+ihandle prom_disp_node __initdata = 0;
+
+prom_entry prom __initdata = 0;
+ihandle prom_chosen __initdata = 0;
+ihandle prom_stdout __initdata = 0;
 
 extern char *klimit;
-char *bootpath = 0;
-char *bootdevice = 0;
+char *bootpath;
+char *bootdevice;
 
-unsigned int rtas_data = 0;   /* physical pointer */
-unsigned int rtas_entry = 0;  /* physical pointer */
-unsigned int rtas_size = 0;
-unsigned int old_rtas = 0;
+unsigned int rtas_data;   /* physical pointer */
+unsigned int rtas_entry;  /* physical pointer */
+unsigned int rtas_size;
+unsigned int old_rtas;
 
 /* Set for a newworld machine */
-int use_of_interrupt_tree = 0;
-int pmac_newworld = 0;
+int use_of_interrupt_tree;
+int pmac_newworld;
 
-static struct device_node *allnodes = 0;
+static struct device_node *allnodes;
 
 #ifdef CONFIG_BOOTX_TEXT
 
@@ -134,13 +137,12 @@
 static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb);
 static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb);
 
-/* We want those in data, not BSS */
-static long				g_loc_X = 0;
-static long				g_loc_Y = 0;
-static long				g_max_loc_X = 0;
-static long				g_max_loc_Y = 0;
+static int g_loc_X;
+static int g_loc_Y;
+static int g_max_loc_X;
+static int g_max_loc_Y;
 
-unsigned long disp_BAT[2] = {0, 0};
+unsigned long disp_BAT[2] __initdata = {0, 0};
 
 #define cmapsz	(16*256)
 
@@ -173,10 +175,10 @@
 void phys_call_rtas(int, int, int, ...);
 
 extern char cmd_line[512];	/* XXX */
-boot_infos_t *boot_infos = 0;	/* init it so it's in data segment not bss */
+boot_infos_t *boot_infos;
 #ifdef CONFIG_BOOTX_TEXT
-boot_infos_t *disp_bi = 0;
-boot_infos_t fake_bi = {0,};
+boot_infos_t *disp_bi;
+boot_infos_t fake_bi;
 #endif
 unsigned long dev_tree_size;
 
@@ -195,10 +197,6 @@
  * OF calls should be done within prom_init(), and prom_init()
  * and all routines called within it must be careful to relocate
  * references as necessary.
- *
- * Note that the bss is cleared *after* prom_init runs, so we have
- * to make sure that any static or extern variables it accesses
- * are put in the data segment.
  */
 #define PTRRELOC(x)	((typeof(x))((unsigned long)(x) + offset))
 #define PTRUNRELOC(x)	((typeof(x))((unsigned long)(x) - offset))
@@ -618,6 +616,11 @@
 	char *p, *d;
 	int prom_version = 0;
  	unsigned long phys;
+	extern char __bss_start, _end;
+
+	/* First zero the BSS -- use memset, some arches don't have
+	 * caches on yet */
+	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
 
  	/* Default */
  	phys = offset + KERNELBASE;
@@ -948,34 +951,6 @@
 		if ((int) call_prom(RELOC("package-to-path"), 3, 1,
 				    node, path, 255) < 0)
 			continue;
-		prom_print(RELOC("opening display "));
-		prom_print(path);
-		ih = call_prom(RELOC("open"), 1, 1, path);
-		if (ih == 0 || ih == (ihandle) -1) {
-			prom_print(RELOC("... failed\n"));
-			continue;
-		}
-		prom_print(RELOC("... ok\n"));
-
-		if (RELOC(prom_disp_node) == 0)
-			RELOC(prom_disp_node) = node;
-			
-		/* Setup a useable color table when the appropriate
-		 * method is available. Should update this to set-colors */
-		for (i = 0; i < 32; i++)
-			if (prom_set_color(ih, i, RELOC(default_colors)[i*3],
-					   RELOC(default_colors)[i*3+1],
-					   RELOC(default_colors)[i*3+2]) != 0)
-				break;
-
-#ifdef CONFIG_FB
-		for (i = 0; i < LINUX_LOGO_COLORS; i++)
-			if (prom_set_color(ih, i + 32,
-					   RELOC(linux_logo_red)[i],
-					   RELOC(linux_logo_green)[i],
-					   RELOC(linux_logo_blue)[i]) != 0)
-				break;
-#endif /* CONFIG_FB */
 
 		/*
 		 * If this display is the device that OF is using for stdout,
@@ -990,9 +965,44 @@
 					= RELOC(prom_display_paths[i-1]);
 		}
 		RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
+		if (i == 0)
+			RELOC(prom_disp_node) = node;
 		if (RELOC(prom_num_displays) >= FB_MAX)
 			break;
 	}
+
+	/*
+	 * Open the first display and set its colormap.
+	 */
+	if (RELOC(prom_num_displays) > 0) {
+		path = PTRRELOC(RELOC(prom_display_paths[0]));
+		prom_print(RELOC("opening display "));
+		prom_print(path);
+		ih = call_prom(RELOC("open"), 1, 1, path);
+		if (ih == 0 || ih == (ihandle) -1) {
+			prom_print(RELOC("... failed\n"));
+		} else {
+			prom_print(RELOC("... ok\n"));
+
+			/* Setup a useable color table when the appropriate
+			 * method is available. Should update this to set-colors */
+			for (i = 0; i < 32; i++)
+				if (prom_set_color(ih, i, RELOC(default_colors)[i*3],
+						   RELOC(default_colors)[i*3+1],
+						   RELOC(default_colors)[i*3+2]) != 0)
+					break;
+
+#ifdef CONFIG_FB
+			for (i = 0; i < LINUX_LOGO_COLORS; i++)
+				if (prom_set_color(ih, i + 32,
+						   RELOC(linux_logo_red)[i],
+						   RELOC(linux_logo_green)[i],
+						   RELOC(linux_logo_blue)[i]) != 0)
+					break;
+#endif /* CONFIG_FB */
+		}
+	}
+
 	return ALIGN(mem);
 }
 
@@ -1277,7 +1287,7 @@
 	if (!strcmp(np->name, "display"))
 		np->name = get_property(np, "compatible", 0);
 
-	if (!strcmp(np->name, "device-tree"))
+	if (np->parent == NULL)
 		ifunc = interpret_root_props;
 	else if (np->type == 0)
 		ifunc = NULL;
@@ -1370,7 +1380,7 @@
 		    np->intrs[i].line = *interrupts++;
 		    if (cvt_irq)
 			np->intrs[i].line = openpic_to_irq(np->intrs[i].line);
-		    np->intrs[i].sense = 0;
+		    np->intrs[i].sense = 1;
 		    if (isize > 1)
 		        np->intrs[i].sense = *interrupts++;
 		    for (j=2; j<isize; j++)
@@ -1540,7 +1550,7 @@
 		for (i = 0; (ml -= cell_size) >= 0; ++i) {
 			if (imp->addr.a_hi == devfn) {
 				np->intrs[np->n_intrs].line = imp->intr;
-				np->intrs[np->n_intrs].sense = 0; /* FIXME */
+				np->intrs[np->n_intrs].sense = 1; /* FIXME */
 				++np->n_intrs;
 			}
 			imp = (struct pci_intr_map *)(((unsigned int)imp)
@@ -1561,7 +1571,7 @@
 		mem_start += np->n_intrs * sizeof(struct interrupt_info);
 		for (i = 0; i < np->n_intrs; ++i) {
 			np->intrs[i].line = *ip++;
-			np->intrs[i].sense = 0;
+			np->intrs[i].sense = 1;
 		}
 	}
 
@@ -1614,7 +1624,7 @@
 		mem_start += np->n_intrs * sizeof(struct interrupt_info);
 		for (i = 0; i < np->n_intrs; ++i) {
 			np->intrs[i].line = *ip++;
-			np->intrs[i].sense = 0;
+			np->intrs[i].sense = 1;
 		}
 	}
 
@@ -1675,7 +1685,7 @@
 				if (keylargo)
 					np->intrs[i].sense = *ip++;
 				else
-					np->intrs[i].sense = 0;
+					np->intrs[i].sense = 1;
 			}
 		} else {
 			/* CHRP machines */
@@ -1771,7 +1781,7 @@
 		mem_start += np->n_intrs * sizeof(struct interrupt_info);
 		for (i = 0; i < np->n_intrs; ++i) {
 			np->intrs[i].line = *ip++;
-			np->intrs[i].sense = 0;
+			np->intrs[i].sense = 1;
 		}
 	}
 
@@ -1779,6 +1789,30 @@
 }
 
 /*
+ * Work out the sense (active-low level / active-high edge)
+ * of each interrupt from the device tree.
+ */
+void __init
+prom_get_irq_senses(unsigned char *senses, int off, int max)
+{
+	struct device_node *np;
+	int i, j;
+
+	/* default to level-triggered */
+	memset(senses, 1, max - off);
+	if (!use_of_interrupt_tree)
+		return;
+
+	for (np = allnodes; np != 0; np = np->allnext) {
+		for (j = 0; j < np->n_intrs; j++) {
+			i = np->intrs[j].line;
+			if (i >= off && i < max)
+				senses[i-off] = np->intrs[j].sense;
+		}
+	}
+}
+
+/*
  * Construct and return a list of the device_nodes with a given name.
  */
 __openfirmware
@@ -1818,39 +1852,6 @@
 	return head;
 }
 
-/* Finds a device node given its PCI bus number, device number
- * and function number
- */
-__openfirmware
-struct device_node *
-find_pci_device_OFnode(unsigned char bus, unsigned char dev_fn)
-{
-	struct device_node* np;
-	unsigned int *reg;
-	int l;
-	
-	for (np = allnodes; np != 0; np = np->allnext) {
-		int in_macio = 0;
-		struct device_node* parent = np->parent;
-		while(parent) {
-			char *pname = (char *)get_property(parent, "name", &l);
-			if (pname && strcmp(pname, "mac-io") == 0) {
-				in_macio = 1;
-				break;
-			}
-			parent = parent->parent;
-		}
-		if (in_macio)
-			continue;
-		reg = (unsigned int *) get_property(np, "reg", &l);
-		if (reg == 0 || l < sizeof(struct reg_property))
-			continue;
-		if (((reg[0] >> 8) & 0xff) == dev_fn && ((reg[0] >> 16) & 0xff) == bus)
-			break;
-	}
-	return np;
-}
-
 /*
  * Returns all nodes linked together
  */
@@ -1981,6 +1982,21 @@
 			return pp->value;
 		}
 	return 0;
+}
+
+/*
+ * Add a property to a node
+ */
+__openfirmware
+void
+prom_add_property(struct device_node* np, struct property* prop)
+{
+	struct property **next = &np->properties;
+
+	prop->next = NULL;	
+	while (*next)
+		next = &(*next)->next;
+	*next = prop;
 }
 
 #if 0
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.4.0/linux/arch/ppc/kernel/setup.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/setup.c	Mon Jan 22 15:41:15 2001
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/blk.h>
 #include <linux/ide.h>
+#include <linux/bootmem.h>
 
 #include <asm/init.h>
 #include <asm/residual.h>
@@ -71,12 +72,6 @@
                       unsigned long r6,
                       unsigned long r7);
 
-extern void gemini_init(unsigned long r3,
-                      unsigned long r4,
-                      unsigned long r5,
-                      unsigned long r6,
-                      unsigned long r7);
-
 #ifdef CONFIG_XMON
 extern void xmon_map_scc(void);
 #endif
@@ -106,6 +101,10 @@
 unsigned long SYSRQ_KEY;
 #endif /* CONFIG_MAGIC_SYSRQ */
 
+#ifdef CONFIG_VGA_CONSOLE
+unsigned long vgacon_remap_base;
+#endif
+
 struct machdep_calls ppc_md;
 
 /*
@@ -377,9 +376,9 @@
 		len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min);
 
 		len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n",
-			       (CD(loops_per_sec)+2500)/500000,
-			       (CD(loops_per_sec)+2500)/5000 % 100);
-		bogosum += CD(loops_per_sec);
+			       (CD(loops_per_jiffy)+2500)/(500000/HZ),
+			       (CD(loops_per_jiffy)+2500)/(5000/HZ) % 100);
+		bogosum += CD(loops_per_jiffy);
 	}
 
 #ifdef CONFIG_SMP
@@ -549,11 +548,6 @@
                 apus_init(r3, r4, r5, r6, r7);
 		break;
 #endif
-#ifdef CONFIG_GEMINI
-	case _MACH_gemini:
-		gemini_init(r3, r4, r5, r6, r7);
-		break;
-#endif
 	default:
 		printk("Unknown machine type in identify_machine!\n");
 	}
@@ -673,13 +667,14 @@
 void __init ppc_init(void)
 {
 	/* clear the progress line */
-	if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
+	if ( ppc_md.progress ) ppc_md.progress("             ", 0xffff);
 	
 	if (ppc_md.init != NULL) {
 		ppc_md.init();
 	}
 }
 
+/* Warning, IO base is not yet inited */
 void __init setup_arch(char **cmdline_p)
 {
 	extern int panic_timeout;
@@ -688,7 +683,7 @@
 	extern void do_init_bootmem(void);
 
 	/* so udelay does something sensible, assume <= 1000 bogomips */
-	loops_per_sec = 500000000;
+	loops_per_jiffy = 500000000 / HZ;
 
 #ifdef CONFIG_ALL_PPC
 	feature_init();
@@ -743,10 +738,34 @@
 	ppc_md.setup_arch();
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
+#ifdef CONFIG_PCI
+	/* We create the "pci-OF-bus-map" property now so it appear in the
+	 * /proc device tree
+	 */
+	if (have_of) {
+		struct property* of_prop;
+		
+		of_prop = (struct property*)alloc_bootmem(sizeof(struct property) + 256);
+		if (of_prop && find_path_device("/")) {
+			memset(of_prop, -1, sizeof(struct property) + 256);
+			of_prop->name = "pci-OF-bus-map";
+			of_prop->length = 256;
+			of_prop->value = (unsigned char *)&of_prop[1];
+			prom_add_property(find_path_device("/"), of_prop);
+		}
+	}
+#endif /* CONFIG_PCI */
+
 	paging_init();
 	sort_exception_table();
 }
 
+/* Convert the shorts/longs in hd_driveid from little to big endian;
+ * chars are endian independant, of course, but strings need to be flipped.
+ * (Despite what it says in drivers/block/ide.h, they come up as little
+ * endian...)
+ *
+ * Changes to linux/hdreg.h may require changes here. */
 void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
 {
         int i;
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c
--- v2.4.0/linux/arch/ppc/kernel/signal.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/signal.c	Wed Jan 24 15:21:19 2001
@@ -53,8 +53,6 @@
 #define MSR_USERCHANGE	(MSR_FE0 | MSR_FE1)
 
 int do_signal(sigset_t *oldset, struct pt_regs *regs);
-extern int sys_wait4(pid_t pid, unsigned long *stat_addr,
-		     int options, unsigned long *ru);
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 {
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.4.0/linux/arch/ppc/kernel/smp.c	Mon Oct 16 12:58:51 2000
+++ linux/arch/ppc/kernel/smp.c	Mon Jan 22 15:41:15 2001
@@ -1,6 +1,4 @@
 /*
- * $Id: smp.c,v 1.68 1999/09/17 19:38:05 cort Exp $
- *
  * Smp support for ppc.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
@@ -8,8 +6,11 @@
  *
  * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
  *
- * Support for PReP (Motorola MTX/MVME) SMP by Troy Benjegerdes
- * (troy@microux.com, hozer@drgw.net)
+ * Support for PReP (Motorola MTX/MVME) and Macintosh G4 SMP 
+ * by Troy Benjegerdes (hozer@drgw.net)
+ *
+ * Support for DayStar quad CPU cards
+ * Copyright (C) XLR8, Inc. 1994-2000
  */
 
 #include <linux/config.h>
@@ -23,7 +24,6 @@
 #define __KERNEL_SYSCALLS__
 #include <linux/unistd.h>
 #include <linux/init.h>
-#include <linux/openpic.h>
 #include <linux/spinlock.h>
 
 #include <asm/ptrace.h>
@@ -37,47 +37,97 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
-#include <asm/gemini.h>
-
+#include <asm/residual.h>
+#include <asm/feature.h>
 #include <asm/time.h>
+
 #include "open_pic.h"
 int smp_threads_ready;
 volatile int smp_commenced;
 int smp_num_cpus = 1;
+int smp_tb_synchronized;
 struct cpuinfo_PPC cpu_data[NR_CPUS];
 struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
-volatile unsigned char active_kernel_processor = NO_PROC_ID;	/* Processor holding kernel spinlock		*/
-volatile unsigned long ipi_count;
+atomic_t ipi_recv;
+atomic_t ipi_sent;
 spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
 unsigned int prof_multiplier[NR_CPUS];
 unsigned int prof_counter[NR_CPUS];
 cycles_t cacheflush_time;
+static int max_cpus __initdata = NR_CPUS;
 
-/* this has to go in the data section because it is accessed from prom_init */
 int smp_hw_index[NR_CPUS];
 
 /* all cpu mappings are 1-1 -- Cort */
 volatile unsigned long cpu_callin_map[NR_CPUS];
 
+#define TB_SYNC_PASSES 4
+volatile unsigned long __initdata tb_sync_flag = 0;
+volatile unsigned long __initdata tb_offset = 0;
+
 int start_secondary(void *);
 extern int cpu_idle(void *unused);
-u_int openpic_read(volatile u_int *addr);
 void smp_call_function_interrupt(void);
 void smp_message_pass(int target, int msg, unsigned long data, int wait);
 
+extern void __secondary_start_psurge(void);
+extern void __secondary_start_psurge2(void);	/* Temporary horrible hack */
+extern void __secondary_start_psurge3(void);	/* Temporary horrible hack */
+
+/* Addresses for powersurge registers */
+#define HAMMERHEAD_BASE		0xf8000000
+#define HHEAD_CONFIG		0x90
+#define HHEAD_SEC_INTR		0xc0
+
 /* register for interrupting the primary processor on the powersurge */
 /* N.B. this is actually the ethernet ROM! */
-#define PSURGE_PRI_INTR	0xf3019000
-/* register for interrupting the secondary processor on the powersurge */
-#define PSURGE_SEC_INTR	0xf80000c0
+#define PSURGE_PRI_INTR		0xf3019000
+
 /* register for storing the start address for the secondary processor */
-#define PSURGE_START	0xf2800000
-/* virtual addresses for the above */
-volatile u32 *psurge_pri_intr;
-volatile u32 *psurge_sec_intr;
-volatile u32 *psurge_start;
+/* N.B. this is the PCI config space address register for the 1st bridge */
+#define PSURGE_START		0xf2800000
+
+/* Daystar/XLR8 4-CPU card */
+#define PSURGE_QUAD_REG_ADDR	0xf8800000
 
-/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. */
+#define PSURGE_QUAD_IRQ_SET	0
+#define PSURGE_QUAD_IRQ_CLR	1
+#define PSURGE_QUAD_IRQ_PRIMARY	2
+#define PSURGE_QUAD_CKSTOP_CTL	3
+#define PSURGE_QUAD_PRIMARY_ARB	4
+#define PSURGE_QUAD_BOARD_ID	6
+#define PSURGE_QUAD_WHICH_CPU	7
+#define PSURGE_QUAD_CKSTOP_RDBK	8
+#define PSURGE_QUAD_RESET_CTL	11
+
+#define PSURGE_QUAD_OUT(r, v)	(out_8((u8 *)(quad_base+((r)<<2)+1), (v)))
+#define PSURGE_QUAD_IN(r)	(in_8((u8 *)(quad_base+((r)<<2)+1)) & 0x0f)
+#define PSURGE_QUAD_BIS(r, v)	(PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
+#define PSURGE_QUAD_BIC(r, v)	(PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
+
+/* virtual addresses for the above */
+static volatile u8 *hhead_base;
+static volatile u32 *quad_base;
+static volatile u32 *psurge_pri_intr;
+static volatile u8 *psurge_sec_intr;
+static volatile u32 *psurge_start;
+
+/* what sort of powersurge board we have */
+static int psurge_type;
+
+/* values for psurge_type */
+#define PSURGE_DUAL		0
+#define PSURGE_QUAD_OKEE	1
+#define PSURGE_QUAD_COTTON	2
+#define PSURGE_QUAD_ICEGRASS	3
+
+/* l2 cache stuff for dual G4 macs */
+extern void core99_init_l2(void);
+
+/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
+ * 
+ * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up
+ * in /proc/interrupts will be wrong!!! --Troy */
 #define PPC_MSG_CALL_FUNCTION	0
 #define PPC_MSG_RESCHEDULE	1
 #define PPC_MSG_INVALIDATE_TLB	2
@@ -85,10 +135,577 @@
 
 static inline void set_tb(unsigned int upper, unsigned int lower)
 {
+	mtspr(SPRN_TBWL, 0);
 	mtspr(SPRN_TBWU, upper);
 	mtspr(SPRN_TBWL, lower);
 }
 
+/*
+ * Set and clear IPIs for powersurge.
+ */
+static inline void psurge_set_ipi(int cpu)
+{
+	if (cpu == 0)
+		in_be32(psurge_pri_intr);
+	else if (psurge_type == PSURGE_DUAL)
+		out_8(psurge_sec_intr, 0);
+	else
+		PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
+}
+
+static inline void psurge_clr_ipi(int cpu)
+{
+	if (cpu > 0) {
+		if (psurge_type == PSURGE_DUAL)
+			out_8(psurge_sec_intr, ~0);
+		else
+			PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
+	}
+}
+
+/*
+ * On powersurge (old SMP powermac architecture) we don't have
+ * separate IPIs for separate messages like openpic does.  Instead
+ * we have a bitmap for each processor, where a 1 bit means that
+ * the corresponding message is pending for that processor.
+ * Ideally each cpu's entry would be in a different cache line.
+ *  -- paulus.
+ */
+static unsigned long psurge_smp_message[NR_CPUS];
+
+void psurge_smp_message_recv(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	int msg;
+
+	/* clear interrupt */
+	psurge_clr_ipi(cpu);
+
+	if (smp_num_cpus < 2)
+		return;
+
+	/* make sure there is a message there */
+	for (msg = 0; msg < 4; msg++)
+		if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
+			smp_message_recv(msg, regs);
+}
+
+void
+psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
+{
+	psurge_smp_message_recv(regs);
+}
+
+static void
+smp_psurge_message_pass(int target, int msg, unsigned long data, int wait)
+{
+	int i;
+
+	if (smp_num_cpus < 2)
+		return;
+
+	for (i = 0; i < smp_num_cpus; i++) {
+		if (target == MSG_ALL
+		    || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())
+		    || target == i) {
+			set_bit(msg, &psurge_smp_message[i]);
+			psurge_set_ipi(i);
+		}
+	}
+}
+
+/*
+ * Determine a quad card presence. We read the board ID register, we
+ * for the data bus to change to something else, and we read it again.
+ * It it's stable, then the register probably exist (ugh !)
+ */
+static int __init psurge_quad_probe(void)
+{
+	int type;
+	unsigned int i;
+
+	type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
+	if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
+	    || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
+		return PSURGE_DUAL;
+
+	/* looks OK, try a slightly more rigorous test */
+	/* bogus is not necessarily cacheline-aligned,
+	   though I don't suppose that really matters.  -- paulus */
+	for (i = 0; i < 100; i++) {
+		volatile u32 bogus[8];
+		bogus[(0+i)%8] = 0x00000000;
+		bogus[(1+i)%8] = 0x55555555;
+		bogus[(2+i)%8] = 0xFFFFFFFF;
+		bogus[(3+i)%8] = 0xAAAAAAAA;
+		bogus[(4+i)%8] = 0x33333333;
+		bogus[(5+i)%8] = 0xCCCCCCCC;
+		bogus[(6+i)%8] = 0xCCCCCCCC;
+		bogus[(7+i)%8] = 0x33333333;
+		wmb();
+		asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
+		mb();
+		if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
+			return PSURGE_DUAL;
+	}
+	return type;
+}
+
+static void __init psurge_quad_init(void)
+{
+	int procbits;
+
+	if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
+	procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
+	if (psurge_type == PSURGE_QUAD_ICEGRASS)
+		PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
+	else
+		PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
+	mdelay(33);
+	out_8(psurge_sec_intr, ~0);
+	PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
+	PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
+	if (psurge_type != PSURGE_QUAD_ICEGRASS)
+		PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
+	PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
+	mdelay(33);
+	PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
+	mdelay(33);
+	PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
+	mdelay(33);
+}
+
+static int __init smp_psurge_probe(void)
+{
+	int i, ncpus;
+
+	/* We don't do SMP on the PPC601 -- paulus */
+	if ((_get_PVR() >> 16) == 1)
+		return 1;
+
+	/*
+	 * The powersurge cpu board can be used in the generation
+	 * of powermacs that have a socket for an upgradeable cpu card,
+	 * including the 7500, 8500, 9500, 9600.
+	 * The device tree doesn't tell you if you have 2 cpus because
+	 * OF doesn't know anything about the 2nd processor.
+	 * Instead we look for magic bits in magic registers,
+	 * in the hammerhead memory controller in the case of the
+	 * dual-cpu powersurge board.  -- paulus.
+	 */
+	if (find_devices("hammerhead") == NULL)
+		return 1;
+
+	hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
+	quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
+	psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
+
+	psurge_type = psurge_quad_probe();
+	if (psurge_type != PSURGE_DUAL) {
+		psurge_quad_init();
+		/* I believe we could "count" CPUs by counting 1 bits
+		 * in procbits on a quad board. For now, we assume 4,
+		 * non-present CPUs will just be seen as "stuck".
+		 * (hope they are the higher-numbered ones -- paulus)
+		 */
+		ncpus = 4;
+	} else {
+		iounmap((void *) quad_base);
+		if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
+			/* not a dual-cpu card */
+			iounmap((void *) hhead_base);
+			return 1;
+		}
+		ncpus = 2;
+	}
+
+	psurge_start = ioremap(PSURGE_START, 4);
+	psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
+
+	/* this is not actually strictly necessary -- paulus. */
+	for (i = 1; i < ncpus; ++i)
+		smp_hw_index[i] = i;
+
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
+
+	return ncpus;
+}
+
+static void __init smp_psurge_kick_cpu(int nr)
+{
+	void (*start)(void) = __secondary_start_psurge;
+
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
+
+	/* setup entry point of secondary processor */
+	switch (nr) {
+	case 2:
+		start = __secondary_start_psurge2;
+		break;
+	case 3:
+		start = __secondary_start_psurge3;
+		break;
+	}
+
+	out_be32(psurge_start, __pa(start));
+	mb();
+
+	psurge_set_ipi(nr);
+	udelay(10);
+	psurge_clr_ipi(nr);
+
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
+}
+
+/*
+ * With the dual-cpu powersurge board, the decrementers and timebases
+ * of both cpus are frozen after the secondary cpu is started up,
+ * until we give the secondary cpu another interrupt.  This routine
+ * uses this to get the timebases synchronized.
+ *  -- paulus.
+ */
+static void __init psurge_dual_sync_tb(int cpu_nr)
+{
+	static volatile int sec_tb_reset = 0;
+	int t;
+
+	set_dec(tb_ticks_per_jiffy);
+	set_tb(0, 0);
+	last_jiffy_stamp(cpu_nr) = 0;
+
+	if (cpu_nr > 0) {
+		mb();
+		sec_tb_reset = 1;
+		return;
+	}
+
+	/* wait for the secondary to have reset its TB before proceeding */
+	for (t = 10000000; t > 0 && !sec_tb_reset; --t)
+		;
+
+	/* now interrupt the secondary, starting both TBs */
+	psurge_set_ipi(1);
+
+	smp_tb_synchronized = 1;
+}
+
+static void
+smp_psurge_setup_cpu(int cpu_nr)
+{
+
+	if (cpu_nr == 0) {
+		if (smp_num_cpus < 2)
+			return;
+		/* reset the entry point so if we get another intr we won't
+		 * try to startup again */
+		out_be32(psurge_start, 0x100);
+		if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0))
+			printk(KERN_ERR "Couldn't get primary IPI interrupt");
+	}
+
+	if (psurge_type == PSURGE_DUAL)
+		psurge_dual_sync_tb(cpu_nr);
+}
+
+
+static void
+smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
+{
+	/* make sure we're sending something that translates to an IPI */
+	if ( msg > 0x3 ){
+		printk("SMP %d: smp_message_pass: unknown msg %d\n",
+		       smp_processor_id(), msg);
+		return;
+	}
+	switch ( target )
+	{
+	case MSG_ALL:
+		openpic_cause_IPI(msg, 0xffffffff);
+		break;
+	case MSG_ALL_BUT_SELF:
+		openpic_cause_IPI(msg,
+       			0xffffffff & ~(1 << smp_hw_index[smp_processor_id()])); 
+
+		break;
+	default:
+		openpic_cause_IPI(msg, smp_hw_index[1<<target]);
+		break;
+	}
+}
+
+static int
+smp_core99_probe(void)
+{
+	struct device_node *cpus;
+	int *pp;
+	int i, ncpus = 1;
+
+	if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
+#if 0	/* Paulus method.. doesn't seem to work on earlier dual G4's??*/
+	cpus = find_devices("cpus");
+	if (cpus != 0) {
+		pp = (int *) get_property(cpus, "#cpus", NULL);
+		if (pp != NULL)
+			ncpus = *pp;
+	}
+#else	/* My original method -- Troy <hozer@drgw.net> */
+	
+	cpus = find_type_devices("cpu");
+	if (cpus){
+		for ( ncpus = 1; cpus->next; cpus = cpus->next ){
+					ncpus++;
+		}
+	}
+#endif
+	printk("smp_core99_probe: OF reports %d cpus\n", ncpus);
+	if (ncpus > 1) {
+		openpic_request_IPIs();
+		for (i = 1; i < ncpus; ++i)
+			smp_hw_index[i] = i;
+	}
+
+	return ncpus;
+}
+
+static void
+smp_core99_kick_cpu(int nr)
+{
+	unsigned long save_int;
+	unsigned long flags;
+	volatile unsigned long *vector
+		 = ((volatile unsigned long *)(KERNELBASE+0x500));
+
+	if (nr != 1)
+		return;
+	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
+
+	local_irq_save(flags);
+	local_irq_disable();
+	
+	/* Save EE vector */
+	save_int = *vector;
+	
+	/* Setup fake EE vector that does	  
+	 *   b __secondary_start_psurge - KERNELBASE
+	 */   
+	*vector = 0x48000002 +
+		((unsigned long)__secondary_start_psurge - KERNELBASE);
+	
+	/* flush data cache and inval instruction cache */
+	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+	
+	/* Put some life in our friend */
+	feature_core99_kick_cpu1();
+	
+	/* FIXME: We wait a bit for the CPU to take the exception, I should
+	 * instead wait for the entry code to set something for me. Well,
+	 * ideally, all that crap will be done in prom.c and the CPU left
+	 * in a RAM-based wait loop like CHRP.
+	 */
+	mdelay(1);
+	
+	/* Restore our exception vector */
+	*vector = save_int;
+	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+	
+	local_irq_restore(flags);
+	if (ppc_md.progress) ppc_md.progress("smp_core99_probe done", 0x347);
+}
+
+static void
+smp_core99_setup_cpu(int cpu_nr)
+{
+	/* Setup openpic */
+	do_openpic_setup_cpu();
+
+	/* Setup L2 */
+	if (cpu_nr != 0)
+		core99_init_l2();
+	else
+		if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+}
+
+static int
+smp_chrp_probe(void)
+{
+	extern unsigned long smp_chrp_cpu_nr;
+
+	if (smp_chrp_cpu_nr > 1)
+		openpic_request_IPIs();
+
+	return smp_chrp_cpu_nr;
+}
+
+static void
+smp_chrp_kick_cpu(int nr)
+{
+	*(unsigned long *)KERNELBASE = nr;
+	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+}
+
+static void
+smp_chrp_setup_cpu(int cpu_nr)
+{
+	static atomic_t ready = ATOMIC_INIT(1);
+	static volatile int frozen = 0;
+
+	if (cpu_nr == 0) {
+		/* wait for all the others */
+		while (atomic_read(&ready) < smp_num_cpus)
+			barrier();
+		atomic_set(&ready, 1);
+		/* freeze the timebase */
+		call_rtas("freeze-time-base", 0, 1, NULL);
+		mb();
+		frozen = 1;
+		/* XXX assumes this is not a 601 */
+		set_tb(0, 0);
+		last_jiffy_stamp(0) = 0;
+		while (atomic_read(&ready) < smp_num_cpus)
+			barrier();
+		/* thaw the timebase again */
+		call_rtas("thaw-time-base", 0, 1, NULL);
+		mb();
+		frozen = 0;
+		smp_tb_synchronized = 1;
+	} else {
+		atomic_inc(&ready);
+		while (!frozen)
+			barrier();
+		set_tb(0, 0);
+		last_jiffy_stamp(0) = 0;
+		mb();
+		atomic_inc(&ready);
+		while (frozen)
+			barrier();
+	}
+
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+}
+
+#ifdef CONFIG_POWER4
+static void
+smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
+{
+	/* for now, only do reschedule messages
+	   since we only have one IPI */
+	if (msg != PPC_MSG_RESCHEDULE)
+		return;
+	for (i = 0; i < smp_num_cpus; ++i) {
+		if (target == MSG_ALL || target == i
+		    || (target == MSG_ALL_BUT_SELF
+			&& i != smp_processor_id()))
+			xics_cause_IPI(i);
+	}
+}
+
+static int
+smp_xics_probe(void)
+{
+	return smp_chrp_cpu_nr;
+}
+
+static void
+smp_xics_setup_cpu(int cpu_nr)
+{
+	if (cpu_nr > 0)
+		xics_setup_cpu();
+}
+#endif /* CONFIG_POWER4 */
+
+static int
+smp_prep_probe(void)
+{
+	extern int mot_multi;
+
+	if (mot_multi) {
+		openpic_request_IPIs();
+		smp_hw_index[1] = 1;
+		return 2;
+	}
+
+	return 1;
+}
+
+static void
+smp_prep_kick_cpu(int nr)
+{
+	extern unsigned long *MotSave_SmpIar;
+	extern unsigned char *MotSave_CpusState[2];
+
+	*MotSave_SmpIar = (unsigned long)__secondary_start_psurge - KERNELBASE;
+	*MotSave_CpusState[1] = CPU_GOOD;
+	printk("CPU1 reset, waiting\n");
+}
+
+static void
+smp_prep_setup_cpu(int cpu_nr)
+{
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+}
+
+static struct smp_ops_t {
+	void  (*message_pass)(int target, int msg, unsigned long data, int wait);
+	int   (*probe)(void);
+	void  (*kick_cpu)(int nr);
+	void  (*setup_cpu)(int nr);
+
+} *smp_ops;
+
+#define smp_message_pass(t,m,d,w) \
+    do { if (smp_ops) \
+	     atomic_inc(&ipi_sent); \
+	     smp_ops->message_pass((t),(m),(d),(w)); \
+       } while(0)
+
+
+/* PowerSurge-style Macs */
+static struct smp_ops_t psurge_smp_ops = {
+	smp_psurge_message_pass,
+	smp_psurge_probe,
+	smp_psurge_kick_cpu,
+	smp_psurge_setup_cpu,
+};
+
+/* Core99 Macs (dual G4s) */
+static struct smp_ops_t core99_smp_ops = {
+	smp_openpic_message_pass,
+	smp_core99_probe,
+	smp_core99_kick_cpu,
+	smp_core99_setup_cpu,
+};
+
+/* CHRP with openpic */
+static struct smp_ops_t chrp_smp_ops = {
+	smp_openpic_message_pass,
+	smp_chrp_probe,
+	smp_chrp_kick_cpu,
+	smp_chrp_setup_cpu,
+};
+
+#ifdef CONFIG_POWER4
+/* CHRP with new XICS interrupt controller */
+static struct smp_ops_t xics_smp_ops = {
+	smp_xics_message_pass,
+	smp_xics_probe,
+	smp_chrp_kick_cpu,
+	smp_xics_setup_cpu,
+};
+#endif /* CONFIG_POWER4 */
+
+/* PReP (MTX) */
+static struct smp_ops_t prep_smp_ops = {
+	smp_openpic_message_pass,
+	smp_prep_probe,
+	smp_prep_kick_cpu,
+	smp_prep_setup_cpu,
+};
+
+/* 
+ * Common functions
+ */
 void smp_local_timer_interrupt(struct pt_regs * regs)
 {
 	int cpu = smp_processor_id();
@@ -101,7 +718,7 @@
 
 void smp_message_recv(int msg, struct pt_regs *regs)
 {
-	ipi_count++;
+	atomic_inc(&ipi_recv);
 	
 	switch( msg ) {
 	case PPC_MSG_CALL_FUNCTION:
@@ -126,47 +743,6 @@
 }
 
 /*
- * As it is now, if we're sending two message at the same time
- * we have race conditions on Pmac.  The PowerSurge doesn't easily
- * allow us to send IPI messages so we put the messages in
- * smp_message[].
- *
- * This is because don't have several IPI's on the PowerSurge even though
- * we do on the chrp.  It would be nice to use actual IPI's such as with
- * openpic rather than this.
- *  -- Cort
- */
-int pmac_smp_message[NR_CPUS];
-void pmac_smp_message_recv(struct pt_regs *regs)
-{
-	int cpu = smp_processor_id();
-	int msg;
-
-	/* clear interrupt */
-	if (cpu == 1)
-		out_be32(psurge_sec_intr, ~0);
-
-	if (smp_num_cpus < 2)
-		return;
-
-	/* make sure there is a message there */
-	msg = pmac_smp_message[cpu];
-	if (msg == 0)
-		return;
-
- 	/* reset message */
-	pmac_smp_message[cpu] = 0;
-
-	smp_message_recv(msg - 1, regs);
-}
-
-void
-pmac_primary_intr(int irq, void *d, struct pt_regs *regs)
-{
-	pmac_smp_message_recv(regs);
-}
-
-/*
  * 750's don't broadcast tlb invalidates so
  * we have to emulate that behavior.
  *   -- Cort
@@ -220,7 +796,7 @@
  */
 static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
 
-static volatile struct call_data_struct {
+static struct call_data_struct {
 	void (*func) (void *info);
 	void *info;
 	atomic_t started;
@@ -317,87 +893,9 @@
 		atomic_inc(&call_data->finished);
 }
 
-void smp_message_pass(int target, int msg, unsigned long data, int wait)
-{
-	if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep|_MACH_gemini)) )
-		return;
-
-	switch (_machine) {
-	case _MACH_Pmac:
-		/*
-		 * IPI's on the Pmac are a hack but without reasonable
-		 * IPI hardware SMP on Pmac is a hack.
-		 *
-		 * We assume here that the msg is not -1.  If it is,
-		 * the recipient won't know the message was destined
-		 * for it. -- Cort
-		 */
-		if (smp_processor_id() == 0) {
-			/* primary cpu */
-			if (target == 1 || target == MSG_ALL_BUT_SELF
-			    || target == MSG_ALL) {
-				pmac_smp_message[1] = msg + 1;
-				/* interrupt secondary processor */
-				out_be32(psurge_sec_intr, ~0);
-				out_be32(psurge_sec_intr, 0);
-			}
-		} else {
-			/* secondary cpu */
-			if (target == 0 || target == MSG_ALL_BUT_SELF
-			    || target == MSG_ALL) {
-				pmac_smp_message[0] = msg + 1;
-				/* interrupt primary processor */
-				in_be32(psurge_pri_intr);
-			}
-		}
-		if (target == smp_processor_id() || target == MSG_ALL) {
-			/* sending a message to ourself */
-			/* XXX maybe we shouldn't do this if ints are off */
-			smp_message_recv(msg, NULL);
-		}
-		break;
-	case _MACH_chrp:
-	case _MACH_prep:
-	case _MACH_gemini:
-#ifndef CONFIG_POWER4
-		/* make sure we're sending something that translates to an IPI */
-		if ( msg > 0x3 )
-			break;
-		switch ( target )
-		{
-		case MSG_ALL:
-			openpic_cause_IPI(smp_processor_id(), msg, 0xffffffff);
-			break;
-		case MSG_ALL_BUT_SELF:
-			openpic_cause_IPI(smp_processor_id(), msg,
-					  0xffffffff & ~(1 << smp_processor_id()));
-			break;
-		default:
-			openpic_cause_IPI(smp_processor_id(), msg, 1<<target);
-			break;
-		}
-#else /* CONFIG_POWER4 */
-		/* for now, only do reschedule messages
-		   since we only have one IPI */
-		if (msg != PPC_MSG_RESCHEDULE)
-			break;
-		for (i = 0; i < smp_num_cpus; ++i) {
-			if (target == MSG_ALL || target == i
-			    || (target == MSG_ALL_BUT_SELF
-				&& i != smp_processor_id()))
-				xics_cause_IPI(i);
-		}
-#endif /* CONFIG_POWER4 */
-		break;
-	}
-}
-
 void __init smp_boot_cpus(void)
 {
 	extern struct task_struct *current_set[NR_CPUS];
-	extern unsigned long smp_chrp_cpu_nr;
-	extern void __secondary_start_psurge(void);
-	extern void __secondary_start_chrp(void);
 	int i, cpu_nr;
 	struct task_struct *p;
 	unsigned long a;
@@ -411,7 +909,6 @@
 	 * cpu 0, the master -- Cort
 	 */
 	cpu_callin_map[0] = 1;
-        active_kernel_processor = 0;
 	current->processor = 0;
 
 	init_idle();
@@ -427,41 +924,40 @@
 	 */
 	cacheflush_time = 5 * 1024;
 
-	if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_gemini)) )
-	{
-		printk("SMP not supported on this machine.\n");
-		return;
-	}
-	
-	switch ( _machine )
-	{
+	/* To be later replaced by some arch-specific routine */
+	switch(_machine) {
 	case _MACH_Pmac:
-		/* assume powersurge board - 2 processors -- Cort */
-		cpu_nr = 2;
-		psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
-		psurge_sec_intr = ioremap(PSURGE_SEC_INTR, 4);
-		psurge_start = ioremap(PSURGE_START, 4);
+		/* Check for Core99 */
+		if (find_devices("uni-n"))
+			smp_ops = &core99_smp_ops;
+		else
+			smp_ops = &psurge_smp_ops;
 		break;
 	case _MACH_chrp:
-		if (OpenPIC)
-			for ( i = 0; i < 4 ; i++ )
-				openpic_enable_IPI(i);
-		cpu_nr = smp_chrp_cpu_nr;
-		break;
-	case _MACH_gemini:
-		for ( i = 0; i < 4 ; i++ )
-			openpic_enable_IPI(i);
-                cpu_nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK)>>2;
-                cpu_nr = (cpu_nr == 0) ? 4 : cpu_nr;
+#ifndef CONFIG_POWER4
+		smp_ops = &chrp_smp_ops;
+#else
+		smp_ops = &xics_smp_ops;
+#endif /* CONFIG_POWER4 */
 		break;
+	case _MACH_prep:
+		smp_ops = &prep_smp_ops;
+		break;
+	default:
+		printk("SMP not supported on this machine.\n");
+		return;
 	}
+	
+	/* Probe arch for CPUs */
+	cpu_nr = smp_ops->probe();
 
 	/*
 	 * only check for cpus we know exist.  We keep the callin map
 	 * with cpus at the bottom -- Cort
 	 */
-	for ( i = 1 ; i < cpu_nr; i++ )
-	{
+	if (cpu_nr > max_cpus)
+		cpu_nr = max_cpus;
+	for (i = 1; i < cpu_nr; i++) {
 		int c;
 		struct pt_regs regs;
 		
@@ -487,25 +983,7 @@
 		asm volatile("sync");
 
 		/* wake up cpus */
-		switch ( _machine )
-		{
-		case _MACH_Pmac:
-			/* setup entry point of secondary processor */
-			out_be32(psurge_start, __pa(__secondary_start_psurge));
-			/* interrupt secondary to begin executing code */
-			out_be32(psurge_sec_intr, ~0);
-			udelay(1);
-			out_be32(psurge_sec_intr, 0);
-			break;
-		case _MACH_chrp:
-			*(unsigned long *)KERNELBASE = i;
-			asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-			break;
-		case _MACH_gemini:
-			openpic_init_processor( 1<<i );
-			openpic_init_processor( 0 );
-			break;
-		}
+		smp_ops->kick_cpu(i);
 		
 		/*
 		 * wait to see if the cpu made a callin (is actually up).
@@ -517,40 +995,108 @@
 		
 		if ( cpu_callin_map[i] )
 		{
+			char buf[32];
+			sprintf(buf, "found cpu %d", i);
+			if (ppc_md.progress) ppc_md.progress(buf, 0x350+i);
 			printk("Processor %d found.\n", i);
 			smp_num_cpus++;
 		} else {
+			char buf[32];
+			sprintf(buf, "didn't find cpu %d", i);
+			if (ppc_md.progress) ppc_md.progress(buf, 0x360+i);
 			printk("Processor %d is stuck.\n", i);
 		}
 	}
 
-	if (OpenPIC && (_machine & (_MACH_gemini|_MACH_chrp|_MACH_prep)))
-		do_openpic_setup_cpu();
+	/* Setup CPU 0 last (important) */
+	smp_ops->setup_cpu(0);
+}
 
-	if ( _machine == _MACH_Pmac )
-	{
-		/* reset the entry point so if we get another intr we won't
-		 * try to startup again */
-		out_be32(psurge_start, 0x100);
-		if (request_irq(30, pmac_primary_intr, 0, "primary IPI", 0))
-			printk(KERN_ERR "Couldn't get primary IPI interrupt");
-		/*
-		 * The decrementers of both cpus are frozen at this point
-		 * until we give the secondary cpu another interrupt.
-		 * We set them both to decrementer_count and then send
-		 * the interrupt.  This should get the decrementers
-		 * synchronized.
-		 * -- paulus.
-		 */
-		set_dec(tb_ticks_per_jiffy);
-		if ((_get_PVR() >> 16) != 1) {
-			set_tb(0, 0);	/* set timebase if not 601 */
-			last_jiffy_stamp(0) = 0;
+void __init smp_software_tb_sync(int cpu)
+{
+#define PASSES 4	/* 4 passes.. */
+	int pass;
+	int i, j;
+
+	/* stop - start will be the number of timebase ticks it takes for cpu0
+	 * to send a message to all others and the first reponse to show up.
+	 *
+	 * ASSUMPTION: this time is similiar for all cpus
+	 * ASSUMPTION: the time to send a one-way message is ping/2
+	 */
+	register unsigned long start = 0;
+	register unsigned long stop = 0;
+	register unsigned long temp = 0;
+	
+	if (smp_num_cpus < 2) {
+		smp_tb_synchronized = 1;
+		return;
+	}
+
+	/* This code need fixing on >2 CPUs --BenH/paulus */
+	if (smp_num_cpus > 2) {
+		smp_tb_synchronized = 0;
+		return;
+	}
+
+	set_tb(0, 0);
+
+	/* multiple passes to get in l1 cache.. */
+	for (pass = 2; pass < 2+PASSES; pass++){
+		if (cpu == 0){
+			mb();
+			for (i = j = 1; i < smp_num_cpus; i++, j++){
+				/* skip stuck cpus */
+				while (!cpu_callin_map[j])
+					++j;
+				while (cpu_callin_map[j] != pass)
+					barrier();
+			}
+			mb();
+			tb_sync_flag = pass;
+			start = get_tbl();	/* start timing */
+			while (tb_sync_flag)
+				mb();
+			stop = get_tbl();	/* end timing */
+			/* theoretically, the divisor should be 2, but
+			 * I get better results on my dual mtx. someone
+			 * please report results on other smp machines..
+			 */
+			tb_offset = (stop-start)/4;
+			mb();
+			tb_sync_flag = pass;
+			udelay(10);
+			mb();
+			tb_sync_flag = 0;
+			mb();
+			set_tb(0,0);
+			mb();
+		} else {
+			cpu_callin_map[cpu] = pass;
+			mb();
+			while (!tb_sync_flag)
+				mb();		/* wait for cpu0 */
+			mb();
+			tb_sync_flag = 0;	/* send response for timing */
+			mb();
+			while (!tb_sync_flag)
+				mb();
+			temp = tb_offset;	/* make sure offset is loaded */
+			while (tb_sync_flag)
+				mb();
+			set_tb(0,temp);		/* now, set the timebase */
+			mb();
 		}
-		out_be32(psurge_sec_intr, ~0);
-		udelay(1);
-		out_be32(psurge_sec_intr, 0);
 	}
+	if (cpu == 0) {
+		smp_tb_synchronized = 1;
+		printk("smp_software_tb_sync: %d passes, final offset: %ld\n",
+			PASSES, tb_offset);
+	}
+	/* so time.c doesn't get confused */
+	set_dec(tb_ticks_per_jiffy);
+	last_jiffy_stamp(cpu) = 0;
+	cpu_callin_map[cpu] = 1;
 }
 
 void __init smp_commence(void)
@@ -558,8 +1104,48 @@
 	/*
 	 *	Lets the callin's below out of their loop.
 	 */
+	if (ppc_md.progress) ppc_md.progress("smp_commence", 0x370);
 	wmb();
 	smp_commenced = 1;
+	/* if the smp_ops->setup_cpu function has not already synched the
+	 * timebases with a nicer hardware-based method, do so now
+	 *
+	 * I am open to suggestions for improvements to this method
+	 * -- Troy <hozer@drgw.net>
+	 *
+	 * NOTE: if you are debugging, set smp_tb_synchronized for now
+	 * since if this code runs pretty early and needs all cpus that
+	 * reported in in smp_callin_map to be working
+	 *
+	 * NOTE2: this code doesn't seem to work on > 2 cpus. -- paulus
+	 */
+	if (!smp_tb_synchronized) {
+		unsigned long flags;
+		__save_and_cli(flags);	
+		smp_software_tb_sync(0);
+		__restore_flags(flags);
+	}
+}
+
+void __init smp_callin(void)
+{
+	int cpu = current->processor;
+	
+        smp_store_cpu_info(cpu);
+	set_dec(tb_ticks_per_jiffy);
+	cpu_callin_map[cpu] = 1;
+
+	smp_ops->setup_cpu(cpu);
+
+	init_idle();
+
+	while(!smp_commenced)
+		barrier();
+	/* see smp_commence for more info */
+	if (!smp_tb_synchronized){
+		smp_software_tb_sync(cpu);
+	}
+	__sti();
 }
 
 /* intel needs this */
@@ -576,37 +1162,6 @@
 	return cpu_idle(NULL);
 }
 
-void __init smp_callin(void)
-{
-        smp_store_cpu_info(current->processor);
-	set_dec(tb_ticks_per_jiffy);
-	if (_machine == _MACH_Pmac && (_get_PVR() >> 16) != 1) {
-		set_tb(0, 0);	/* set timebase if not 601 */
-		last_jiffy_stamp(current->processor) = 0;
-	}
-	init_idle();
-	cpu_callin_map[current->processor] = 1;
-
-#ifndef CONFIG_POWER4
-	/*
-	 * Each processor has to do this and this is the best
-	 * place to stick it for now.
-	 *  -- Cort
-	 */
-	if (OpenPIC && _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep))
-		do_openpic_setup_cpu();
-#else
-	xics_setup_cpu();
-#endif /* CONFIG_POWER4 */
-#ifdef CONFIG_GEMINI	
-	if ( _machine == _MACH_gemini )
-		gemini_init_l2();
-#endif
-	while(!smp_commenced)
-		barrier();
-	__sti();
-}
-
 void __init smp_setup(char *str, int *ints)
 {
 }
@@ -621,6 +1176,14 @@
         struct cpuinfo_PPC *c = &cpu_data[id];
 
 	/* assume bogomips are same for everything */
-        c->loops_per_sec = loops_per_sec;
+        c->loops_per_jiffy = loops_per_jiffy;
         c->pvr = _get_PVR();
 }
+
+static int __init maxcpus(char *str)
+{
+	get_option(&str, &max_cpus);
+	return 1;
+}
+
+__setup("maxcpus=", maxcpus);
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.4.0/linux/arch/ppc/kernel/time.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/time.c	Mon Jan 22 15:41:15 2001
@@ -67,7 +67,12 @@
 
 #include <asm/time.h>
 
-void smp_local_timer_interrupt(struct pt_regs *);
+#ifdef CONFIG_SMP
+extern void smp_local_timer_interrupt(struct pt_regs *);
+extern int smp_tb_synchronized;
+#endif /* CONFIG_SMP */
+
+extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
 
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
@@ -97,6 +102,36 @@
 	return delta;
 }
 
+extern unsigned long prof_cpu_mask;
+extern unsigned int * prof_buffer;
+extern unsigned long prof_len;
+extern unsigned long prof_shift;
+extern char _stext;
+
+static inline void ppc_do_profile (unsigned long nip)
+{
+	if (!prof_buffer)
+		return;
+
+	/*
+	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
+	 * (default is all CPUs.)
+	 */
+	if (!((1<<smp_processor_id()) & prof_cpu_mask))
+		return;
+
+	nip -= (unsigned long) &_stext;
+	nip >>= prof_shift;
+	/*
+	 * Don't ignore out-of-bounds EIP values silently,
+	 * put them into the last histogram slot, so if
+	 * present, they will show up as a sharp peak.
+	 */
+	if (nip > prof_len-1)
+		nip = prof_len-1;
+	atomic_inc((atomic_t *)&prof_buffer[nip]);
+}
+
 /*
  * timer_interrupt - gets called when the decrementer overflows,
  * with interrupts disabled.
@@ -110,6 +145,9 @@
 
 	hardirq_enter(cpu);
 	
+	if (!user_mode(regs))
+		ppc_do_profile(instruction_pointer(regs));
+
 	do { 
 		jiffy_stamp += tb_ticks_per_jiffy;
 	  	if (smp_processor_id()) continue;
@@ -151,7 +189,7 @@
 
 #ifdef CONFIG_SMP
 	smp_local_timer_interrupt(regs);
-#endif		
+#endif /* CONFIG_SMP */
 	
 	if (ppc_md.heartbeat && !ppc_md.heartbeat_count--)
 		ppc_md.heartbeat();
@@ -176,7 +214,7 @@
 	/* As long as timebases are not in sync, gettimeofday can only
 	 * have jiffy resolution on SMP.
 	 */
-	if (_machine != _MACH_Pmac)
+	if (!smp_tb_synchronized)
 		delta = 0;
 #endif /* CONFIG_SMP */
 	lost_ticks = jiffies - wall_jiffies;
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.4.0/linux/arch/ppc/kernel/traps.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/traps.c	Mon Jan 22 15:41:15 2001
@@ -65,21 +65,37 @@
 void (*debugger_fault_handler)(struct pt_regs *regs);
 #endif
 #endif
+
 /*
  * Trap & Exception support
  */
 
+
+spinlock_t oops_lock = SPIN_LOCK_UNLOCKED;
+
+void die(const char * str, struct pt_regs * fp, long err)
+{
+	console_verbose();
+	spin_lock_irq(&oops_lock);
+	printk("Oops: %s, sig: %ld\n", str, err);
+	show_regs(fp);
+	print_backtrace((unsigned long *)fp->gpr[1]);
+	spin_unlock_irq(&oops_lock);
+	/* do_exit() should take care of panic'ing from an interrupt
+	 * context so we don't handle it here
+	 */
+	do_exit(err);
+}
+
 void
 _exception(int signr, struct pt_regs *regs)
 {
 	if (!user_mode(regs))
 	{
-		show_regs(regs);
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 		debugger(regs);
 #endif
-		print_backtrace((unsigned long *)regs->gpr[1]);
-		panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+		die("Exception in kernel mode", regs, signr);
 	}
 	force_sig(signr, current);
 }
@@ -98,7 +114,7 @@
 
 #if defined(CONFIG_8xx) && defined(CONFIG_PCI)
 	/* the qspan pci read routines can cause machine checks -- Cort */
-	bad_page_fault(regs, regs->dar);
+	bad_page_fault(regs, regs->dar, SIGBUS);
 	return;
 #endif
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
@@ -151,12 +167,10 @@
 	default:
 		printk("Unknown values in msr\n");
 	}
-	show_regs(regs);
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 	debugger(regs);
 #endif
-	print_backtrace((unsigned long *)regs->gpr[1]);
-	panic("machine check");
+	die("machine check", regs, SIGBUS);
 }
 
 void
@@ -217,13 +231,13 @@
 	uint    rd;
 	uint    retval;
 
-	retval = EFAULT;
+	retval = EINVAL;
 
 	if (!user_mode(regs))
 		return retval;
 
 	if (get_user(instword, (uint *)(regs->nip)))
-		return retval;
+		return EFAULT;
 
 	/* Emulate the mfspr rD, PVR.
 	 */
@@ -337,12 +351,10 @@
 	int errcode;
 
 	if (!user_mode(regs)) {
-		show_regs(regs);
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 		debugger(regs);
 #endif
-		print_backtrace((unsigned long *)regs->gpr[1]);
-		panic("Kernel Mode Software FPU Emulation");
+		die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
 	}
 
 #ifdef CONFIG_MATH_EMULATION
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/lib/Makefile linux/arch/ppc/lib/Makefile
--- v2.4.0/linux/arch/ppc/lib/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/ppc/lib/Makefile	Mon Jan 22 15:41:15 2001
@@ -9,6 +9,6 @@
 
 obj-y			:= checksum.o string.o strcase.o
 
-obj-$(CONFIG_SMP)	:= locks.o
+obj-$(CONFIG_SMP)	+= locks.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/lib/locks.c linux/arch/ppc/lib/locks.c
--- v2.4.0/linux/arch/ppc/lib/locks.c	Thu Oct  7 10:17:08 1999
+++ linux/arch/ppc/lib/locks.c	Mon Jan 22 15:41:15 2001
@@ -58,8 +58,9 @@
 {
 #ifdef DEBUG_LOCKS
   	if ( !lp->lock )
-		printk("_spin_unlock(%p): no lock cpu %d %s/%d\n", lp,
-		      smp_processor_id(),current->comm,current->pid);
+		printk("_spin_unlock(%p): no lock cpu %d curr PC %p %s/%d\n",
+		       lp, smp_processor_id(), __builtin_return_address(0),
+		       current->comm, current->pid);
 	if ( lp->owner_cpu != smp_processor_id() )
 		printk("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n",
 		      lp, smp_processor_id(), (int)lp->owner_cpu,
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/mbxboot/vmlinux.lds linux/arch/ppc/mbxboot/vmlinux.lds
--- v2.4.0/linux/arch/ppc/mbxboot/vmlinux.lds	Mon May 15 14:53:30 2000
+++ linux/arch/ppc/mbxboot/vmlinux.lds	Wed Dec 31 16:00:00 1969
@@ -1,152 +0,0 @@
-OUTPUT_ARCH(powerpc)
-SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
-/* Do we need any of these for elf?
-   __DYNAMIC = 0;    */
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = + SIZEOF_HEADERS;
-  .interp : { *(.interp) }
-  .hash          : { *(.hash)		}
-  .dynsym        : { *(.dynsym)		}
-  .dynstr        : { *(.dynstr)		}
-  .rel.text      : { *(.rel.text)		}
-  .rela.text     : { *(.rela.text) 	}
-  .rel.data      : { *(.rel.data)		}
-  .rela.data     : { *(.rela.data) 	}
-  .rel.rodata    : { *(.rel.rodata) 	}
-  .rela.rodata   : { *(.rela.rodata) 	}
-  .rel.got       : { *(.rel.got)		}
-  .rela.got      : { *(.rela.got)		}
-  .rel.ctors     : { *(.rel.ctors)	}
-  .rela.ctors    : { *(.rela.ctors)	}
-  .rel.dtors     : { *(.rel.dtors)	}
-  .rela.dtors    : { *(.rela.dtors)	}
-  .rel.bss       : { *(.rel.bss)		}
-  .rela.bss      : { *(.rela.bss)		}
-  .rel.plt       : { *(.rel.plt)		}
-  .rela.plt      : { *(.rela.plt)		}
-/*  .init          : { *(.init)	} =0*/
-  .plt : { *(.plt) }
-  .text      :
-  {
-    *(.text)
-    *(.fixup)
-    *(.got1)
-  }
-  _etext = .;
-  PROVIDE (etext = .);
-  .rodata    :
-  {
-    *(.rodata)
-    *(.rodata1)
-  }
-  .fini      : { *(.fini)    } =0
-  .ctors     : { *(.ctors)   }
-  .dtors     : { *(.dtors)   }
-  /* Read-write section, merged into data segment: */
-  . = (. + 0x0FFF) & 0xFFFFF000;
-  .data    :
-  {
-    *(.data)
-    *(.data1)
-    *(.sdata)
-    *(.sdata2)
-    *(.got.plt) *(.got)
-    *(.dynamic)
-    CONSTRUCTORS
-  }
-  _edata  =  .;
-  PROVIDE (edata = .);
-
-  .fixup   : { *(.fixup) }
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  . = ALIGN(4096);
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { 
-    *(.data.init);
-    __vtop_table_begin = .;
-    *(.vtop_fixup);
-    __vtop_table_end = .;
-    __ptov_table_begin = .;
-    *(.ptov_fixup);
-    __ptov_table_end = .;
-  }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);
-  __init_end = .;
-
-  . = ALIGN(4096);
-  __pmac_begin = .;
-  .text.pmac : { *(.text.pmac) }
-  .data.pmac : { *(.data.pmac) }
-  . = ALIGN(4096);
-  __pmac_end = .;
-
-  . = ALIGN(4096);
-  __prep_begin = .;
-  .text.prep : { *(.text.prep) }
-  .data.prep : { *(.data.prep) }
-  . = ALIGN(4096);
-  __prep_end = .;
-
-  . = ALIGN(4096);
-  __apus_begin = .;
-  .text.apus : { *(.text.apus) }
-  .data.apus : { *(.data.apus) }
-  . = ALIGN(4096);
-  __apus_end = .;
-
-  . = ALIGN(4096);
-  __apus_begin = .;
-  .text.apus : { *(.text.apus) }
-  .data.apus : { *(.data.apus) }
-  . = ALIGN(4096);
-  __apus_end = .;
-
-  . = ALIGN(4096);
-  __openfirmware_begin = .;
-  .text.openfirmware : { *(.text.openfirmware) }
-  .data.openfirmware : { *(.data.openfirmware) }
-  . = ALIGN(4096);
-  __openfirmware_end = .;
-
-  __bss_start = .;
-  .bss       :
-  {
-   *(.sbss) *(.scommon)
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  }
-  _end = . ;
-  PROVIDE (end = .);
-
-  /*
-   * For loader only: Put the zImage after everything else
-   */
-  _gzstart = . ;
-  .gzimage : { *(.gzimage) }
-  _gzend   = . ;
-  
-  /*
-   * For loader only: Put the initrd after zImage
-   */
-  _rdstart = . ;
-  .rdimage : { *(.rdimage) }
-  _rdend   = . ;
-  
-}
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v2.4.0/linux/arch/ppc/mm/fault.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/mm/fault.c	Mon Jan 22 15:41:15 2001
@@ -48,7 +48,7 @@
 unsigned int probingmem = 0;
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
-void bad_page_fault(struct pt_regs *, unsigned long);
+void bad_page_fault(struct pt_regs *, unsigned long, int sig);
 void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
 
 /*
@@ -96,7 +96,7 @@
 #endif /* CONFIG_XMON || CONFIG_KGDB */
 
 	if (in_interrupt() || mm == NULL) {
-		bad_page_fault(regs, address);
+		bad_page_fault(regs, address, SIGSEGV);
 		return;
 	}
 	down(&mm->mmap_sem);
@@ -182,7 +182,7 @@
 		return;
 	}
 
-	bad_page_fault(regs, address);
+	bad_page_fault(regs, address, SIGSEGV);
 	return;
 
 /*
@@ -194,7 +194,7 @@
 	printk("VM: killing process %s\n", current->comm);
 	if (user_mode(regs))
 		do_exit(SIGKILL);
-	bad_page_fault(regs, address);
+	bad_page_fault(regs, address, SIGKILL);
 	return;
 
 do_sigbus:
@@ -205,7 +205,7 @@
 	info.si_addr = (void *)address;
 	force_sig_info (SIGBUS, &info, current);
 	if (!user_mode(regs))
-		bad_page_fault(regs, address);
+		bad_page_fault(regs, address, SIGBUS);
 }
 
 /*
@@ -214,8 +214,10 @@
  * in traps.c.
  */
 void
-bad_page_fault(struct pt_regs *regs, unsigned long address)
+bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
 {
+	extern void die(const char *,struct pt_regs *,long);
+
 	unsigned long fixup;
 
 	/* Are we prepared to handle this fault?  */
@@ -225,14 +227,11 @@
 	}
 
 	/* kernel has accessed a bad area */
-	show_regs(regs);
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 	if (debugger_kernel_faults)
 		debugger(regs);
 #endif
-	print_backtrace( (unsigned long *)regs->gpr[1] );
-	panic("kernel access of bad area pc %lx lr %lx address %lX tsk %s/%d",
-	      regs->nip,regs->link,address,current->comm,current->pid);
+	die("kernel access of bad area", regs, sig);
 }
 
 #ifdef CONFIG_8xx
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.4.0/linux/arch/ppc/mm/init.c	Tue Nov 28 22:43:39 2000
+++ linux/arch/ppc/mm/init.c	Mon Jan 22 15:41:15 2001
@@ -34,7 +34,6 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/openpic.h>
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -62,7 +61,6 @@
 #include <asm/machdep.h>
 #include <asm/setup.h>
 #include <asm/amigahw.h>
-#include <asm/gemini.h>
 
 #include "mem_pieces.h"
 
@@ -70,15 +68,17 @@
 #include "4xx_tlb.h"
 #endif
 
-#define MAX_LOW_MEM	(640 << 20)
+#define MAX_LOW_MEM	(512 << 20)
 
 #define	PGTOKB(pages)	(((pages) * PAGE_SIZE) >> 10)
 
 int prom_trashed;
 atomic_t next_mmu_context;
+rwlock_t context_overflow_lock __cacheline_aligned = RW_LOCK_UNLOCKED;
 unsigned long *end_of_DRAM;
 unsigned long total_memory;
 unsigned long total_lowmem;
+unsigned long ram_phys_base;
 int mem_init_done;
 int init_bootmem_done;
 int boot_mapsize;
@@ -114,7 +114,6 @@
 unsigned long prep_find_end_of_memory(void);
 unsigned long pmac_find_end_of_memory(void);
 unsigned long apus_find_end_of_memory(void);
-unsigned long gemini_find_end_of_memory(void);
 extern unsigned long find_end_of_memory(void);
 #ifdef CONFIG_8xx
 unsigned long m8xx_find_end_of_memory(void);
@@ -127,14 +126,13 @@
 #endif /* CONFIG_8260 */
 static void mapin_ram(void);
 void map_page(unsigned long va, unsigned long pa, int flags);
-void set_phys_avail(struct mem_pieces *mp);
+void set_phys_avail(unsigned long total_ram);
 extern void die_if_kernel(char *,struct pt_regs *,long);
 
 extern char _start[], _end[];
 extern char _stext[], etext[];
 extern struct task_struct *current_set[NR_CPUS];
 
-struct mem_pieces phys_mem;
 char *klimit = _end;
 struct mem_pieces phys_avail;
 
@@ -199,6 +197,8 @@
 
 /* max amount of RAM to use */
 unsigned long __max_memory;
+/* max amount of low RAM to map in */
+unsigned long __max_low_memory = MAX_LOW_MEM;
 
 void __bad_pte(pmd_t *pmd)
 {
@@ -399,8 +399,8 @@
 	 * If the address lies within the first 16 MB, assume it's in ISA
 	 * memory space
 	 */
-	if (p < 16*1024*1024)
-	    p += _ISA_MEM_BASE;
+	if ( p < 16*1024*1024 )
+		p += _ISA_MEM_BASE;
 
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using.
@@ -437,7 +437,11 @@
 			return NULL;
 		v = VMALLOC_VMADDR(area->addr);
 	} else {
+#ifndef CONFIG_HIGHMEM
 		if (p >= ioremap_base)
+#else
+		if (p >= ioremap_base && p < PKMAP_BASE)
+#endif /* CONFIG_HIGHMEM */
 			v = p;
 		else
 			v = (ioremap_bot -= size);
@@ -491,16 +495,13 @@
 void
 map_page(unsigned long va, unsigned long pa, int flags)
 {
-	pmd_t *pd, oldpd;
+	pmd_t *pd;
 	pte_t *pg;
 
 	/* Use upper 10 bits of VA to index the first level map */
 	pd = pmd_offset(pgd_offset_k(va), va);
-	oldpd = *pd;
 	/* Use middle 10 bits of VA to index the second-level map */
 	pg = pte_alloc(pd, va);
-	if (pmd_none(oldpd) && mem_init_done)
-		set_pgdir(va, *(pgd_t *)pd);
 	set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
 	if (mem_init_done)
 		flush_hash_page(0, va);
@@ -532,6 +533,8 @@
 	 * 0xd0000000 on 64-bit machines. */
 	flush_hash_segments(0xd, 0xffffff);
 #else
+	/* this could cause problems on SMP with nobats  -- paulus */
+	/* XXX no hash_table_lock?  interesting  -- paulus */
 	__clear_user(Hash, Hash_size);
 	_tlbia();
 #ifdef CONFIG_SMP
@@ -548,6 +551,27 @@
 void
 local_flush_tlb_mm(struct mm_struct *mm)
 {
+	if (mm->context == 0) {
+		/* don't try to reassign a new context to the kernel */
+		/*
+		 * This could cause problems on SMP if we aren't using
+		 * the BATs (e.g. on POWER4 or if the nobats option is used).
+		 * The problem scenario is that one cpu is doing
+		 * flush_hash_page or similar when another cpu clears
+		 * out the HPTEs which map the flush_hash_page text
+		 * and the hash table.  hash_page will then deadlock.
+		 * We need some way to have "protected" HPTEs or else
+		 * do all hash-table manipulation with the MMU off.
+		 *  -- paulus.
+		 */
+#ifdef CONFIG_PPC64BRIDGE
+		flush_hash_segments(0xd, 0xf);
+#else
+		flush_hash_segments(0xc, 0xf);
+#endif CONFIG_PPC64BRIDGE
+		_tlbia();
+		return;
+	}
 	mm->context = NO_CONTEXT;
 	if (mm == current->mm)
 		activate_mm(mm, mm);
@@ -581,16 +605,18 @@
 {
 	start &= PAGE_MASK;
 
-	if (end - start > 20 * PAGE_SIZE)
-	{
-		flush_tlb_mm(mm);
-		return;
+	if (mm->context != 0) {
+		if (end > TASK_SIZE)
+			end = TASK_SIZE;
+		if (end - start > 20 * PAGE_SIZE) {
+			flush_tlb_mm(mm);
+			return;
+		}
 	}
 
-	for (; start < end && start < TASK_SIZE; start += PAGE_SIZE)
-	{
+	for (; start < end; start += PAGE_SIZE)
 		flush_hash_page(mm->context, start);
-	}
+
 #ifdef CONFIG_SMP
 	smp_send_tlb_invalidate(0);
 #endif	
@@ -608,23 +634,36 @@
 	struct task_struct *tsk;
 
 	printk(KERN_DEBUG "mmu_context_overflow\n");
-	read_lock(&tasklist_lock);
- 	for_each_task(tsk) {
-		if (tsk->mm)
-			tsk->mm->context = NO_CONTEXT;
-	}
-	read_unlock(&tasklist_lock);
-	flush_hash_segments(0x10, 0xffffff);
+	/* acquire the write lock for context overflow */
+	write_lock (&context_overflow_lock);
+	/* recheck if overflow still exists */
+	if (atomic_read(&next_mmu_context) == LAST_CONTEXT) {
+		read_lock(&tasklist_lock);
+		for_each_task(tsk) {
+			if (tsk->mm)
+				tsk->mm->context = NO_CONTEXT;
+		}
+		read_unlock(&tasklist_lock);
+		flush_hash_segments(0x10, 0xffffff);
 #ifdef CONFIG_SMP
-	smp_send_tlb_invalidate(0);
+		smp_send_tlb_invalidate(0);
 #endif	
-	atomic_set(&next_mmu_context, 0);
+		atomic_set(&next_mmu_context, 0);
+	}
+	write_unlock (&context_overflow_lock);
 	/* make sure current always has a context */
-	current->mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));
-	/* The PGD is only a placeholder.  It is only used on
-	 * 8xx processors.
-	 */
-	set_context(current->mm->context, current->mm->pgd);
+	/* need to check to assure current task has an mm */
+	/*   - idle thread does not have an MM */
+	if (current->mm) {
+		current->mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));
+		set_context(current->mm->context, current->mm->pgd);
+	}
+}
+#else /* CONFIG_8xx */
+void
+mmu_context_overflow(void)
+{
+	atomic_set(&next_mmu_context, -1);
 }
 #endif /* CONFIG_8xx */
 
@@ -727,22 +766,20 @@
 
 static void __init mapin_ram(void)
 {
-	int i;
 	unsigned long v, p, s, f;
 
 #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
 	if (!__map_without_bats) {
-		unsigned long tot, mem_base, bl, done;
+		unsigned long tot, bl, done;
 		unsigned long max_size = (256<<20);
 		unsigned long align;
 
 		/* Set up BAT2 and if necessary BAT3 to cover RAM. */
-		mem_base = __pa(KERNELBASE);
 
 		/* Make sure we don't map a block larger than the
 		   smallest alignment of the physical address. */
-		/* alignment of mem_base */
-		align = ~(mem_base-1) & mem_base;
+		/* alignment of ram_phys_base */
+		align = ~(ram_phys_base-1) & ram_phys_base;
 		/* set BAT block size to MIN(max_size, align) */
 		if (align && align < max_size)
 			max_size = align;
@@ -753,7 +790,7 @@
 				break;
 		}
 
-		setbat(2, KERNELBASE, mem_base, bl, RAM_PAGE);
+		setbat(2, KERNELBASE, ram_phys_base, bl, RAM_PAGE);
 		done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
 		if ((done < tot) && !bat_addrs[3].limit) {
 			/* use BAT3 to cover a bit more */
@@ -761,41 +798,35 @@
 			for (bl = 128<<10; bl < max_size; bl <<= 1)
 				if (bl * 2 > tot)
 					break;
-			setbat(3, KERNELBASE+done, mem_base+done, bl, 
+			setbat(3, KERNELBASE+done, ram_phys_base+done, bl, 
 			       RAM_PAGE);
 		}
 	}
 #endif /* !CONFIG_4xx && !CONFIG_8xx && !CONFIG_POWER4 */
 
-	for (i = 0; i < phys_mem.n_regions; ++i) {
-		v = (ulong)__va(phys_mem.regions[i].address);
-		p = phys_mem.regions[i].address;
-		if (p >= total_lowmem)
-			break;
-		for (s = 0; s < phys_mem.regions[i].size; s += PAGE_SIZE) {
-                        /* On the MPC8xx, we want the page shared so we
-                         * don't get ASID compares on kernel space.
-                         */
-			f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
+	v = KERNELBASE;
+	p = ram_phys_base;
+	for (s = 0; s < total_lowmem; s += PAGE_SIZE) {
+		/* On the MPC8xx, we want the page shared so we
+		 * don't get ASID compares on kernel space.
+		 */
+		f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
 #if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
- 			/* Allows stub to set breakpoints everywhere */
- 			f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
+		/* Allows stub to set breakpoints everywhere */
+		f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
 #else
-			if ((char *) v < _stext || (char *) v >= etext)
-				f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
+		if ((char *) v < _stext || (char *) v >= etext)
+			f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
 #ifndef CONFIG_8xx
-			else
-				/* On the powerpc (not 8xx), no user access
-				   forces R/W kernel access */
-				f |= _PAGE_USER;
+		else
+			/* On the powerpc (not 8xx), no user access
+			   forces R/W kernel access */
+			f |= _PAGE_USER;
 #endif /* CONFIG_8xx */
 #endif /* CONFIG_KGDB */
-			map_page(v, p, f);
-			v += PAGE_SIZE;
-			p += PAGE_SIZE;
-			if (p >= total_lowmem)
-				break;
-		}
+		map_page(v, p, f);
+		v += PAGE_SIZE;
+		p += PAGE_SIZE;
 	}
 }
 
@@ -922,27 +953,64 @@
         mtspr(SPRN_DCCR, 0x80000000);	/* 128 MB of data space at 0x0. */
         mtspr(SPRN_ICCR, 0x80000000);	/* 128 MB of instr. space at 0x0. */
 }
-#else
-	/* How about ppc_md.md_find_end_of_memory instead of these
-	 * ifdefs?  -- Dan.
-	 */
-#ifdef CONFIG_BOOTX_TEXT
-extern boot_infos_t *disp_bi;
+
+#elif defined(CONFIG_8xx)
+void __init MMU_init(void)
+{
+	if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
+
+	total_memory = total_lowmem = m8xx_find_end_of_memory();
+#ifdef CONFIG_HIGHMEM
+	if (total_lowmem > MAX_LOW_MEM) {
+		total_lowmem = MAX_LOW_MEM;
+		mem_pieces_remove(&phys_avail, total_lowmem,
+				  total_memory - total_lowmem, 0);
+	}
+#endif /* CONFIG_HIGHMEM */
+	end_of_DRAM = __va(total_lowmem);
+	set_phys_avail(total_lowmem);
+
+        /* Map in all of RAM starting at KERNELBASE */
+        mapin_ram();
+
+        /* Now map in some of the I/O space that is generically needed
+         * or shared with multiple devices.
+         * All of this fits into the same 4Mbyte region, so it only
+         * requires one page table page.
+         */
+        ioremap(IMAP_ADDR, IMAP_SIZE);
+#ifdef CONFIG_MBX
+        ioremap(NVRAM_ADDR, NVRAM_SIZE);
+        ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE);
+        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
+
+	/* Map some of the PCI/ISA I/O space to get the IDE interface.
+	*/
+        ioremap(PCI_ISA_IO_ADDR, 0x4000);
+        ioremap(PCI_IDE_ADDR, 0x4000);
+#endif
+#ifdef CONFIG_RPXLITE
+	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
+	ioremap(HIOX_CSR_ADDR, HIOX_CSR_SIZE);
+#endif
+#ifdef CONFIG_RPXCLASSIC
+        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
+	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
 #endif
+	if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
+}
+
+#else /* not 4xx or 8xx */
 void __init MMU_init(void)
 {
 	if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
-#ifndef CONFIG_8xx
+
 	if (have_of)
 		total_memory = pmac_find_end_of_memory();
 #ifdef CONFIG_APUS
 	else if (_machine == _MACH_apus )
 		total_memory = apus_find_end_of_memory();
 #endif
-#ifdef CONFIG_GEMINI	
-	else if ( _machine == _MACH_gemini )
-		total_memory = gemini_find_end_of_memory();
-#endif /* CONFIG_GEMINI	*/
 #if defined(CONFIG_8260)
 	else
 		total_memory = m8260_find_end_of_memory();
@@ -950,16 +1018,17 @@
 	else /* prep */
 		total_memory = prep_find_end_of_memory();
 #endif
-
+	if (__max_memory && total_memory > __max_memory)
+		total_memory = __max_memory;
 	total_lowmem = total_memory;
-#ifdef CONFIG_HIGHMEM
-	if (total_lowmem > MAX_LOW_MEM) {
-		total_lowmem = MAX_LOW_MEM;
-		mem_pieces_remove(&phys_avail, total_lowmem,
-				  total_memory - total_lowmem, 0);
-	}
+	if (total_lowmem > __max_low_memory) {
+		total_lowmem = __max_low_memory;
+#ifndef CONFIG_HIGHMEM
+		total_memory = total_lowmem;
 #endif /* CONFIG_HIGHMEM */
+	}
 	end_of_DRAM = __va(total_lowmem);
+	set_phys_avail(total_lowmem);
 
 	if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300);
         hash_init();
@@ -991,12 +1060,15 @@
 		ioremap_base = 0xf0000000;
 		break;
 	case _MACH_chrp:
-		setbat(0, 0xf8000000, 0xf8000000, 0x08000000, IO_PAGE);
-#ifdef CONFIG_PPC64BRIDGE
-		setbat(1, 0x80000000, 0xc0000000, 0x10000000, IO_PAGE);
-#else
-		setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
-		setbat(3, 0x90000000, 0x90000000, 0x10000000, IO_PAGE);
+		/*
+		 * The code below tends to get removed, please don't take it out.
+		 * The F50 needs this mapping and it you take it out I'll track you
+		 * down and slap your hands.  If it causes problems please email me.
+		 *  -- Cort <cort@fsmlabs.com>
+		 */
+#ifndef CONFIG_POWER3
+		setbat(0, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
+		setbat(1, 0x90000000, 0x90000000, 0x10000000, IO_PAGE);
 #endif
 		break;
 	case _MACH_Pmac:
@@ -1008,10 +1080,6 @@
 		/* Map chip and ZorroII memory */
 		setbat(1, zTwoBase,   0x00000000, 0x01000000, IO_PAGE);
 		break;
-	case _MACH_gemini:
-		setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
-		setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
-		break;
 	case _MACH_8260:
 		/* Map the IMMR, plus anything else we can cover
 		 * in that upper space according to the memory controller
@@ -1025,46 +1093,7 @@
 	}
 	ioremap_bot = ioremap_base;
 #endif /* CONFIG_POWER4 */
-#else /* CONFIG_8xx */
-
-	total_memory = total_lowmem = m8xx_find_end_of_memory();
-#ifdef CONFIG_HIGHMEM
-	if (total_lowmem > MAX_LOW_MEM) {
-		total_lowmem = MAX_LOW_MEM;
-		mem_pieces_remove(&phys_avail, total_lowmem,
-				  total_memory - total_lowmem, 0);
-	}
-#endif /* CONFIG_HIGHMEM */
-	end_of_DRAM = __va(total_lowmem);
-
-        /* Map in all of RAM starting at KERNELBASE */
-        mapin_ram();
-
-        /* Now map in some of the I/O space that is generically needed
-         * or shared with multiple devices.
-         * All of this fits into the same 4Mbyte region, so it only
-         * requires one page table page.
-         */
-        ioremap(IMAP_ADDR, IMAP_SIZE);
-#ifdef CONFIG_MBX
-        ioremap(NVRAM_ADDR, NVRAM_SIZE);
-        ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE);
-        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
 
-	/* Map some of the PCI/ISA I/O space to get the IDE interface.
-	*/
-        ioremap(PCI_ISA_IO_ADDR, 0x4000);
-        ioremap(PCI_IDE_ADDR, 0x4000);
-#endif
-#ifdef CONFIG_RPXLITE
-	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
-	ioremap(HIOX_CSR_ADDR, HIOX_CSR_SIZE);
-#endif
-#ifdef CONFIG_RPXCLASSIC
-        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
-	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
-#endif
-#endif /* CONFIG_8xx */
 	if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
 #ifdef CONFIG_BOOTX_TEXT
 	/* Must be done last, or ppc_md.progress will die */
@@ -1189,7 +1218,8 @@
 #if defined(CONFIG_ALL_PPC)	
 	/* mark the RTAS pages as reserved */
 	if ( rtas_data )
-		for (addr = rtas_data; addr < PAGE_ALIGN(rtas_data+rtas_size) ;
+		for (addr = (ulong)__va(rtas_data);
+		     addr < PAGE_ALIGN((ulong)__va(rtas_data)+rtas_size) ;
 		     addr += PAGE_SIZE)
 			SetPageReserved(virt_to_page(addr));
 #endif /* defined(CONFIG_ALL_PPC) */
@@ -1249,7 +1279,7 @@
 unsigned long __init pmac_find_end_of_memory(void)
 {
 	unsigned long a, total;
-	unsigned long ram_limit = 0xe0000000 - KERNELBASE;
+	struct mem_pieces phys_mem;
 
 	memory_node = find_devices("memory");
 	if (memory_node == NULL) {
@@ -1260,8 +1290,7 @@
 	/*
 	 * Find out where physical memory is, and check that it
 	 * starts at 0 and is contiguous.  It seems that RAM is
-	 * always physically contiguous on Power Macintoshes,
-	 * because MacOS can't cope if it isn't.
+	 * always physically contiguous on Power Macintoshes.
 	 *
 	 * Supporting discontiguous physical memory isn't hard,
 	 * it just makes the virtual <-> physical mapping functions
@@ -1274,23 +1303,14 @@
 	a = phys_mem.regions[0].address;
 	if (a != 0)
 		panic("RAM doesn't start at physical address 0");
-	if (__max_memory == 0 || __max_memory > ram_limit)
-		__max_memory = ram_limit;
-	if (phys_mem.regions[0].size >= __max_memory) {
-		phys_mem.regions[0].size = __max_memory;
-		phys_mem.n_regions = 1;
-	}
 	total = phys_mem.regions[0].size;
-	
+
 	if (phys_mem.n_regions > 1) {
 		printk("RAM starting at 0x%x is not contiguous\n",
 		       phys_mem.regions[1].address);
 		printk("Using RAM from 0 to 0x%lx\n", total-1);
-		phys_mem.n_regions = 1;
 	}
 
-	set_phys_avail(&phys_mem);
-
 	return total;
 }
 #endif /* CONFIG_ALL_PPC */
@@ -1305,7 +1325,11 @@
 unsigned long __init prep_find_end_of_memory(void)
 {
 	unsigned long total;
+#ifdef CONFIG_PREP_RESIDUAL
 	total = res->TotalMemory;
+#else
+	total = 0;
+#endif
 
 	if (total == 0 )
 	{
@@ -1317,33 +1341,11 @@
 		total = 0x02000000;
 		printk("Ramsize default to be %ldM\n", total>>20);
 	}
-	mem_pieces_append(&phys_mem, 0, total);
-	set_phys_avail(&phys_mem);
 
 	return (total);
 }
 #endif /* defined(CONFIG_ALL_PPC) */
 
-
-#if defined(CONFIG_GEMINI)
-unsigned long __init gemini_find_end_of_memory(void)
-{
-	unsigned long total;
-	unsigned char reg;
-
-	reg = readb(GEMINI_MEMCFG);
-	total = ((1<<((reg & 0x7) - 1)) *
-		 (8<<((reg >> 3) & 0x7)));
-	total *= (1024*1024);
-	phys_mem.regions[0].address = 0;
-	phys_mem.regions[0].size = total;
-	phys_mem.n_regions = 1;
-	
-	set_phys_avail(&phys_mem);
-	return phys_mem.regions[0].size;
-}
-#endif /* defined(CONFIG_GEMINI) */
-
 #ifdef CONFIG_8260
 /*
  * Same hack as 8xx.
@@ -1355,12 +1357,7 @@
 	
 	binfo = (bd_t *)__res;
 
-	phys_mem.regions[0].address = 0;
-	phys_mem.regions[0].size = binfo->bi_memsize;	
-	phys_mem.n_regions = 1;
-	
-	set_phys_avail(&phys_mem);
-	return phys_mem.regions[0].size;
+	return binfo->bi_memsize;
 }
 #endif /* CONFIG_8260 */
 
@@ -1369,6 +1366,7 @@
 unsigned long __init apus_find_end_of_memory(void)
 {
 	int shadow = 0;
+	unsigned long total;
 
 	/* The memory size reported by ADOS excludes the 512KB
 	   reserved for PPC exception registers and possibly 512KB
@@ -1394,43 +1392,28 @@
 		memory[0].size = ((size+0x001fffff) & 0xffe00000);
 	}
 
-	/* Now register the memory block. */
-	mem_pieces_append(&phys_mem, memory[0].addr, memory[0].size);
-	set_phys_avail(&phys_mem);
+	total = memory[0].size;
 
 	/* Remove the memory chunks that are controlled by special
            Phase5 hardware. */
-	{
-		unsigned long top = memory[0].addr + memory[0].size;
 
-		/* Remove the upper 512KB if it contains a shadow of
-		   the ADOS ROM. FIXME: It might be possible to
-		   disable this shadow HW. Check the booter
-		   (ppc_boot.c) */
-		if (shadow)
-		{
-			top -= HARDWARE_MAPPED_SIZE;
-			mem_pieces_remove(&phys_avail, top,
-					  HARDWARE_MAPPED_SIZE, 0);
-		}
-
-		/* Remove the upper 512KB where the PPC exception
-                   vectors are mapped. */
-		top -= HARDWARE_MAPPED_SIZE;
-#if 0
-		/* This would be neat, but it breaks on A3000 machines!? */
-		mem_pieces_remove(&phys_avail, top, 16384, 0);
-#else
-		mem_pieces_remove(&phys_avail, top, HARDWARE_MAPPED_SIZE, 0);
-#endif
-
-	}
+	/* Remove the upper 512KB if it contains a shadow of
+	   the ADOS ROM. FIXME: It might be possible to
+	   disable this shadow HW. Check the booter
+	   (ppc_boot.c) */
+	if (shadow)
+		total -= HARDWARE_MAPPED_SIZE;
+
+	/* Remove the upper 512KB where the PPC exception
+	   vectors are mapped. */
+	total -= HARDWARE_MAPPED_SIZE;
 
 	/* Linux/APUS only handles one block of memory -- the one on
 	   the PowerUP board. Other system memory is horrible slow in
 	   comparison. The user can use other memory for swapping
 	   using the z2ram device. */
-	return memory[0].addr + memory[0].size;
+	ram_phys_base = memory[0].addr;
+	return total;
 }
 #endif /* CONFIG_APUS */
 
@@ -1440,12 +1423,11 @@
 static void __init hash_init(void)
 {
 	int Hash_bits, mb, mb2;
-	unsigned int hmask, ramsize, h;
+	unsigned int hmask, h;
 
 	extern unsigned int hash_page_patch_A[], hash_page_patch_B[],
 		hash_page_patch_C[], hash_page[];
 
-	ramsize = (ulong)end_of_DRAM - KERNELBASE;
 #ifdef CONFIG_PPC64BRIDGE
 	/* The hash table has already been allocated and initialized
 	   in prom.c */
@@ -1464,7 +1446,7 @@
 	 * Allow 64k of hash table for every 16MB of memory,
 	 * up to a maximum of 2MB.
 	 */
-	for (h = 64<<10; h < ramsize / 256 && h < (2<<20); h *= 2)
+	for (h = 64<<10; h < total_memory / 256 && h < (2<<20); h *= 2)
 		;
 	Hash_size = h;
 	Hash_mask = (h >> 6) - 1;
@@ -1498,8 +1480,8 @@
 		Hash = 0;
 #endif /* CONFIG_PPC64BRIDGE */
 
-	printk("Total memory = %dMB; using %ldkB for hash table (at %p)\n",
-	       ramsize >> 20, Hash_size >> 10, Hash);
+	printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
+	       total_memory >> 20, Hash_size >> 10, Hash);
 	if ( Hash_size )
 	{
 		if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
@@ -1560,12 +1542,7 @@
 	
 	binfo = (bd_t *)__res;
 
-	phys_mem.regions[0].address = 0;
-	phys_mem.regions[0].size = binfo->bi_memsize;	
-	phys_mem.n_regions = 1;
-
-	set_phys_avail(&phys_mem);
-	return phys_mem.regions[0].address + phys_mem.regions[0].size;
+	return binfo->bi_memsize;
 }
 #endif /* !CONFIG_4xx && !CONFIG_8xx */
 
@@ -1582,20 +1559,16 @@
 	unsigned long *ret;
 	bd_t *bip = (bd_t *)__res;
 	
-	phys_mem.regions[0].address = 0;
-	phys_mem.regions[0].size = bip->bi_memsize;
-	phys_mem.n_regions = 1;
-
-	set_phys_avail(&phys_mem);
-	return (phys_mem.regions[0].address + phys_mem.regions[0].size);
+	return bip->bi_memsize;
 }
 #endif
 
 /*
- * Set phys_avail to phys_mem less the kernel text/data/bss.
+ * Set phys_avail to the amount of physical memory,
+ * less the kernel text/data/bss.
  */
 void __init
-set_phys_avail(struct mem_pieces *mp)
+set_phys_avail(unsigned long total_memory)
 {
 	unsigned long kstart, ksize;
 
@@ -1604,7 +1577,9 @@
 	 * physical memory.
 	 */
 
-	phys_avail = *mp;
+	phys_avail.regions[0].address = 0;
+	phys_avail.regions[0].size = total_memory;
+	phys_avail.n_regions = 1;
 
 	/*
 	 * Map out the kernel text/data/bss from the available physical
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c
--- v2.4.0/linux/arch/ppc/xmon/start.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/xmon/start.c	Mon Jan 22 15:41:15 2001
@@ -14,6 +14,10 @@
 #include <asm/bootx.h>
 #include <asm/feature.h>
 #include <asm/processor.h>
+#include <asm/delay.h>
+#ifdef CONFIG_SMP
+#include <asm/bitops.h>
+#endif
 
 static volatile unsigned char *sccc, *sccd;
 unsigned long TXRDY, RXRDY;
@@ -22,10 +26,10 @@
 extern void prom_drawstring(const char *str);
 static int xmon_expect(const char *str, unsigned int timeout);
 
-static int console = 0;
-static int use_screen = 1; /* default */
-static int via_modem = 0;
-static int xmon_use_sccb = 0;
+static int console;
+static int use_screen;
+static int via_modem = 1;
+static int xmon_use_sccb;
 static struct device_node *macio_node;
 
 #define TB_SPEED	25000000
@@ -53,28 +57,32 @@
 
 	use_screen = 0;
 	
-	if ( _machine == _MACH_Pmac )
-	{
+	if (_machine == _MACH_Pmac) {
 		struct device_node *np;
 		unsigned long addr;
 #ifdef CONFIG_BOOTX_TEXT
 		extern boot_infos_t *disp_bi;
 
+		/* see if there is a keyboard in the device tree
+		   with a parent of type "adb" */
+		for (np = find_devices("keyboard"); np; np = np->next)
+			if (np->parent && np->parent->type
+			    && strcmp(np->parent->type, "adb") == 0)
+				break;
+
 		/* needs to be hacked if xmon_printk is to be used
  		   from within find_via_pmu() */
 #ifdef CONFIG_ADB_PMU
-		if (!via_modem && disp_bi && find_via_pmu()) {
-			prom_drawstring("xmon uses screen and keyboard\n");
+		if (np != NULL && disp_bi && find_via_pmu())
 			use_screen = 1;
-		}
 #endif
 #ifdef CONFIG_ADB_CUDA
-		if (!via_modem && disp_bi ) {
-			prom_drawstring("xmon uses screen and keyboard\n");
+		if (np != NULL && disp_bi && find_via_cuda())
 			use_screen = 1;
-		}
-#endif
 #endif
+		if (use_screen)
+			prom_drawstring("xmon uses screen and keyboard\n");
+#endif /* CONFIG_BOOTX_TEXT */
 
 #ifdef CHRP_ESCC
 		addr = 0xc1013020;
@@ -93,15 +101,6 @@
 		sccc = base + (addr & ~PAGE_MASK);
 		sccd = sccc + 0x10;
 	}
-	else if ( _machine & _MACH_gemini )
-	{
-		/* should already be mapped by the kernel boot */
-		sccc = (volatile unsigned char *) 0xffeffb0d;
-		sccd = (volatile unsigned char *) 0xffeffb08;
-		TXRDY = 0x20;
-		RXRDY = 1;
-		console = 1;
-	}
 	else
 	{
 		/* should already be mapped by the kernel boot */
@@ -140,12 +139,22 @@
 	char *p = ptr;
 	int i, c, ct;
 
+#ifdef CONFIG_SMP
+	static unsigned long xmon_write_lock;
+	int lock_wait = 1000000;
+	int locked;
+
+	while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
+		if (--lock_wait == 0)
+			break;
+#endif
+
 #ifdef CONFIG_BOOTX_TEXT
 	if (use_screen) {
 		/* write it on the screen */
 		for (i = 0; i < nb; ++i)
 			prom_drawchar(*p++);
-		return nb;
+		goto out;
 	}
 #endif
 	if (!scc_initialized)
@@ -166,8 +175,15 @@
 		}
 		buf_access();
 		*sccd = c;
+		eieio();
 	}
-	return i;
+
+ out:
+#ifdef CONFIG_SMP
+	if (!locked)
+		clear_bit(0, &xmon_write_lock);
+#endif
+	return nb;
 }
 
 int xmon_wants_key;
diff -u --recursive --new-file v2.4.0/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- v2.4.0/linux/arch/ppc/xmon/xmon.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/xmon/xmon.c	Mon Jan 22 15:41:15 2001
@@ -406,6 +406,7 @@
 			break;
 		case 'M':
 			print_sysmap();
+			break;
 		case 'S':
 			super_regs();
 			break;
@@ -795,6 +796,8 @@
 	extern char *sysmap;
 	if ( sysmap )
 		printf("System.map: \n%s", sysmap);
+	else
+		printf("No System.map\n");
 }
 
 void
diff -u --recursive --new-file v2.4.0/linux/arch/s390/kernel/signal.c linux/arch/s390/kernel/signal.c
--- v2.4.0/linux/arch/s390/kernel/signal.c	Sun Sep  3 11:53:42 2000
+++ linux/arch/s390/kernel/signal.c	Wed Jan 24 15:23:06 2001
@@ -52,8 +52,6 @@
 	struct ucontext uc;
 } rt_sigframe;
 
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-			 int options, unsigned long *ru);
 asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
 
 /*
diff -u --recursive --new-file v2.4.0/linux/arch/sh/boot/compressed/head.S linux/arch/sh/boot/compressed/head.S
--- v2.4.0/linux/arch/sh/boot/compressed/head.S	Fri Dec 29 14:07:20 2000
+++ linux/arch/sh/boot/compressed/head.S	Sun Jan 28 18:56:00 2001
@@ -43,7 +43,7 @@
 end_addr:
 	.long	_end
 init_sr:
-	.long	0x40000000	/* Privileged mode, Bank=0, Block=0, I3-I0=0 */
+	.long	0x400000F0	/* Privileged mode, Bank=0, Block=0, IMASK=0xF */
 init_stack_addr:
 	.long	stack_start
 decompress_kernel_addr:
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S
--- v2.4.0/linux/arch/sh/kernel/entry.S	Fri Oct 13 12:06:52 2000
+++ linux/arch/sh/kernel/entry.S	Sun Jan 28 18:56:00 2001
@@ -36,23 +36,23 @@
  * NOTE: This code uses a convention that instructions in the delay slot
  * of a transfer-control instruction are indented by an extra space, thus:
  *
- *    jmp	@$k0	    ! control-transfer instruction
- *     ldc	$k1, $ssr   ! delay slot
+ *    jmp	@k0	    ! control-transfer instruction
+ *     ldc	k1, ssr     ! delay slot
  *
  * Stack layout in 'ret_from_syscall':
  * 	ptrace needs to have all regs on the stack.
  *	if the order here is changed, it needs to be
  *	updated in ptrace.c and ptrace.h
  *
- *	$r0
+ *	r0
  *      ...
- *	$r15 = stack pointer
- *	$spc
- *	$pr
- *	$ssr
- *	$gbr
- *	$mach
- *	$macl
+ *	r15 = stack pointer
+ *	spc
+ *	pr
+ *	ssr
+ *	gbr
+ *	mach
+ *	macl
  *	syscall #
  *
  */
@@ -88,16 +88,16 @@
 #endif
 
 /* Offsets to the stack */
-R0         =  0		/* Return value. New ABI also arg4 */
-R1         =  4     	/* New ABI: arg5 */
-R2         =  8     	/* New ABI: arg6 */
-R3         =  12     	/* New ABI: syscall_nr */
-R4         =  16     	/* New ABI: arg0 */
-R5         =  20     	/* New ABI: arg1 */
-R6         =  24     	/* New ABI: arg2 */
-R7         =  28     	/* New ABI: arg3 */
-SP	   =  (15*4)
-SR	   =  (16*4+8)
+OFF_R0         =  0		/* Return value. New ABI also arg4 */
+OFF_R1         =  4     	/* New ABI: arg5 */
+OFF_R2         =  8     	/* New ABI: arg6 */
+OFF_R3         =  12     	/* New ABI: syscall_nr */
+OFF_R4         =  16     	/* New ABI: arg0 */
+OFF_R5         =  20     	/* New ABI: arg1 */
+OFF_R6         =  24     	/* New ABI: arg2 */
+OFF_R7         =  28     	/* New ABI: arg3 */
+OFF_SP	   =  (15*4)
+OFF_SR	   =  (16*4+8)
 SYSCALL_NR =  (16*4+6*4)
 
 
@@ -140,117 +140,139 @@
 !
 
 #define STI()				\
-	mov.l	__INV_IMASK, $r11;	\
-	stc	$sr, $r10;		\
-	and	$r11, $r10;		\
-	stc	$k_g_imask, $r11;	\
-	or	$r11, $r10;		\
-	ldc	$r10, $sr
+	mov.l	__INV_IMASK, r11;	\
+	stc	sr, r10;		\
+	and	r11, r10;		\
+	stc	k_g_imask, r11;	\
+	or	r11, r10;		\
+	ldc	r10, sr
 
 	.align	2
 tlb_miss_load:
 	bra	call_dpf
-	 mov	#0, $r5
+	 mov	#0, r5
 
 	.align	2
 tlb_miss_store:
 	bra	call_dpf
-	 mov	#1, $r5
+	 mov	#1, r5
 
 	.align	2
 initial_page_write:
 	bra	call_dpf
-	 mov	#1, $r5
+	 mov	#1, r5
 
 	.align	2
 tlb_protection_violation_load:
 	bra	call_dpf
-	 mov	#0, $r5
+	 mov	#0, r5
 
 	.align	2
 tlb_protection_violation_store:
 	bra	call_dpf
-	 mov	#1, $r5
+	 mov	#1, r5
 
 call_dpf:
-	mov.l	1f, $r0
-	mov	$r5, $r8
-	mov.l	@$r0, $r6
-	mov	$r6, $r9
-	mov.l	2f, $r0
-	sts	$pr, $r10
-	jsr	@$r0
-	 mov	$r15, $r4
+	mov.l	1f, r0
+	mov	r5, r8
+	mov.l	@r0, r6
+	mov	r6, r9
+	mov.l	2f, r0
+	sts	pr, r10
+	jsr	@r0
+	 mov	r15, r4
 	!
-	tst	#0xff, $r0
+	tst	#0xff, r0
 	bf/s	0f
-	 lds	$r10, $pr
+	 lds	r10, pr
 	rts
 	 nop
 0:	STI()
-	mov.l	3f, $r0
-	mov	$r9, $r6
-	mov	$r8, $r5
-	jmp	@$r0
-	 mov	$r15, $r4
+	mov.l	3f, r0
+	mov	r9, r6
+	mov	r8, r5
+	jmp	@r0
+	 mov	r15, r4
 
 	.align 2
 1:	.long	MMU_TEA
 2:	.long	SYMBOL_NAME(__do_page_fault)
 3:	.long	SYMBOL_NAME(do_page_fault)
 
+	.align	2
+address_error_load:
+	bra	call_dae
+	 mov	#0,r5		! writeaccess = 0
+
+	.align	2
+address_error_store:
+	bra	call_dae
+	 mov	#1,r5		! writeaccess = 1
+
+call_dae:
+	mov.l	1f, r0
+	mov.l	@r0, r6		! address
+	mov.l	2f, r0
+	jmp	@r0
+	 mov	r15, r4		! regs
+
+	.align 2
+1:	.long	MMU_TEA
+2:	.long   SYMBOL_NAME(do_address_error)
+
 #if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)
 	.align	2
 	/* Unwind the stack and jmp to the debug entry */
 debug_kernel:
-	mov.l	@$r15+, $r0
-	mov.l	@$r15+, $r1
-	mov.l	@$r15+, $r2
-	mov.l	@$r15+, $r3
-	mov.l	@$r15+, $r4
-	mov.l	@$r15+, $r5
-	mov.l	@$r15+, $r6
-	mov.l	@$r15+, $r7
-	stc	$sr, $r8
-	mov.l	1f, $r9			! BL =1, RB=1, IMASK=0x0F
-	or	$r9, $r8
-	ldc	$r8, $sr		! here, change the register bank
-	mov.l	@$r15+, $r8
-	mov.l	@$r15+, $r9
-	mov.l	@$r15+, $r10
-	mov.l	@$r15+, $r11
-	mov.l	@$r15+, $r12
-	mov.l	@$r15+, $r13
-	mov.l	@$r15+, $r14
-	mov.l	@$r15+, $k0
-	ldc.l	@$r15+, $spc
-	lds.l	@$r15+, $pr
-	mov.l	@$r15+, $k1
-	ldc.l	@$r15+, $gbr
-	lds.l	@$r15+, $mach
-	lds.l	@$r15+, $macl
-	mov	$k0, $r15
-	!
-	mov.l	2f, $k0
-	jmp	@$k0
-	 ldc	$k1, $ssr
+	mov.l	@r15+, r0
+	mov.l	@r15+, r1
+	mov.l	@r15+, r2
+	mov.l	@r15+, r3
+	mov.l	@r15+, r4
+	mov.l	@r15+, r5
+	mov.l	@r15+, r6
+	mov.l	@r15+, r7
+	stc	sr, r8
+	mov.l	1f, r9			! BL =1, RB=1, IMASK=0x0F
+	or	r9, r8
+	ldc	r8, sr			! here, change the register bank
+	mov.l	@r15+, r8
+	mov.l	@r15+, r9
+	mov.l	@r15+, r10
+	mov.l	@r15+, r11
+	mov.l	@r15+, r12
+	mov.l	@r15+, r13
+	mov.l	@r15+, r14
+	mov.l	@r15+, k0
+	ldc.l	@r15+, spc
+	lds.l	@r15+, pr
+	mov.l	@r15+, k1
+	ldc.l	@r15+, gbr
+	lds.l	@r15+, mach
+	lds.l	@r15+, macl
+	mov	k0, r15
+	!
+	mov.l	2f, k0
+	mov.l	@k0, k0
+	jmp	@k0
+	 ldc	k1, ssr
 	.align	2
 1:	.long	0x300000f0
-2:	.long	CONFIG_GDB_STUB_VBR + 0x100
+2:	.long	SYMBOL_NAME(gdb_vbr_vector)
 #endif
 
 	.align	2
 debug_trap:	
 #if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)
-	mov	#SR, $r0
-	mov.l	@($r0,$r15), $r0	! get status register
-	shll	$r0
-	shll	$r0			! kernel space?
+	mov	#OFF_SR, r0
+	mov.l	@(r0,r15), r0		! get status register
+	shll	r0
+	shll	r0			! kernel space?
 	bt/s	debug_kernel
 #endif
-	 mov.l	@$r15, $r0
-	mov.l	1f, $r8
-	jmp	@$r8
+	 mov.l	@r15, r0
+	mov.l	1f, r8
+	jmp	@r8
 	 nop
 
 	.align	2
@@ -260,8 +282,8 @@
 error:	
 	!
 	STI()
-	mov.l	1f, $r0
-	jmp	@$r0
+	mov.l	1f, r0
+	jmp	@r0
 	 nop
 	.align	2
 1:	.long	SYMBOL_NAME(do_exception_error)
@@ -272,7 +294,7 @@
 !
 ENTRY(ret_from_fork)
 	bra	SYMBOL_NAME(ret_from_syscall)
-	 add	#4, $r15	! pop down bogus r0 (see switch_to MACRO)
+	 add	#4, r15	! pop down bogus r0 (see switch_to MACRO)
 
 /*
  * Old syscall interface:
@@ -305,90 +327,90 @@
  */
 
 system_call:
-	mov.l	__TRA, $r9
-	mov.l	@$r9, $r8
+	mov.l	__TRA, r9
+	mov.l	@r9, r8
 	!
 	! Is the trap argument >= 0x20? (TRA will be >= 0x80)
-	mov	#0x20, $r9
-	extu.b	$r9, $r9
-	shll2	$r9
-	cmp/hs	$r9, $r8
+	mov	#0x20, r9
+	extu.b	r9, r9
+	shll2	r9
+	cmp/hs	r9, r8
 	bt	debug_trap
 	!
-	mov	#SYSCALL_NR, $r14
-	add	$r15, $r14
+	mov	#SYSCALL_NR, r14
+	add	r15, r14
 	!
 #ifdef COMPAT_OLD_SYSCALL_ABI
-	mov	#0x40, $r9
-	cmp/hs	$r9, $r8
+	mov	#0x40, r9
+	cmp/hs	r9, r8
 	bf/s	old_abi_system_call
 	 nop
 #endif
 	! New Syscall ABI
-	add	#-0x40, $r8
-	shlr2	$r8
-	shll8	$r8
-	shll8	$r8 	    	! $r8 = num_args<<16
-	mov	$r3, $r10
-	or	$r8, $r10	! Encode syscall # and # of arguments
-	mov.l	$r10, @$r14	! set syscall_nr
+	add	#-0x40, r8
+	shlr2	r8
+	shll8	r8
+	shll8	r8 		    	! r8 = num_args<<16
+	mov	r3, r10
+	or	r8, r10	! Encode syscall # and # of arguments
+	mov.l	r10, @r14		! set syscall_nr
 	STI()
 	!
-	stc	$k_current, $r11
-	mov.l	@(tsk_ptrace,$r11), $r10	! Is current PTRACE_SYSCALL'd?
-	mov	#PT_TRACESYS, $r11
-	tst	$r11, $r10
+	stc	k_current, r11
+	mov.l	@(tsk_ptrace,r11), r10	! Is current PTRACE_SYSCALL'd?
+	mov	#PT_TRACESYS, r11
+	tst	r11, r10
 	bt	5f
 	!                     	Yes it is traced.
-	mov.l	__syscall_trace, $r11	! Call syscall_trace() which notifies
-	jsr	@$r11	    	    	! superior (will chomp $R[0-7])
+	mov.l	__syscall_trace, r11	! Call syscall_trace() which notifies
+	jsr	@r11	    	    	! superior (will chomp R[0-7])
 	 nop
-	!			Reload $R0-$R4 from kernel stack, where the
+	!			Reload R0-R4 from kernel stack, where the
 	!   	    	    	parent may have modified them using
-	!   	    	    	ptrace(POKEUSR).  (Note that $R0-$R2 are
+	!   	    	    	ptrace(POKEUSR).  (Note that R0-R2 are
 	!   	    	    	used by the system call handler directly
 	!   	    	    	from the kernel stack anyway, so don't need
 	!   	    	    	to be reloaded here.)  This allows the parent
 	!   	    	    	to rewrite system calls and args on the fly.
-	mov.l	@(R4,$r15), $r4   ! arg0
-	mov.l	@(R5,$r15), $r5
-	mov.l	@(R6,$r15), $r6
-	mov.l	@(R7,$r15), $r7   ! arg3
-	mov.l	@(R3,$r15), $r3   ! syscall_nr
+	mov.l	@(OFF_R4,r15), r4   ! arg0
+	mov.l	@(OFF_R5,r15), r5
+	mov.l	@(OFF_R6,r15), r6
+	mov.l	@(OFF_R7,r15), r7   ! arg3
+	mov.l	@(OFF_R3,r15), r3   ! syscall_nr
 	!   	    	    Arrange for syscall_trace() to be called
 	!   	    	    again as the system call returns.
-	mov.l	__syscall_ret_trace, $r10
+	mov.l	__syscall_ret_trace, r10
 	bra	6f
-	 lds	$r10, $pr
+	 lds	r10, pr
 	!   	    	    No it isn't traced.
 	!   	    	    Arrange for normal system call return.
-5:	mov.l	__syscall_ret, $r10
-	lds	$r10, $pr
+5:	mov.l	__syscall_ret, r10
+	lds	r10, pr
 	!   	    	    Call the system call handler through the table.
 	!   	    	    (both normal and ptrace'd)
 	!   	    	    First check for bad syscall number
-6:	mov	$r3, $r9
-	mov.l	__n_sys, $r10
-	cmp/hs	$r10, $r9
+6:	mov	r3, r9
+	mov.l	__n_sys, r10
+	cmp/hs	r10, r9
 	bf	2f
 	!   	    	    Bad syscall number
 	rts			! go to syscall_ret or syscall_ret_trace
-    	 mov	#-ENOSYS, $r0
+    	 mov	#-ENOSYS, r0
 	!   	    	    Good syscall number
-2:	shll2	$r9		! x4
-	mov.l	__sct, $r11
-	add	$r11, $r9
-	mov.l	@$r9, $r11
-	jmp	@$r11	    	! jump to specific syscall handler
+2:	shll2	r9		! x4
+	mov.l	__sct, r11
+	add	r11, r9
+	mov.l	@r9, r11
+	jmp	@r11	    	! jump to specific syscall handler
 	 nop
 
 	! In case of trace
 syscall_ret_trace:
-	mov.l	$r0, @(R0,$r15)		! save the return value
-	mov.l	__syscall_trace, $r1
-	mova	SYMBOL_NAME(ret_from_syscall), $r0
-	jmp	@$r1    	! Call syscall_trace() which notifies superior
-	 lds	$r0, $pr    	! Then return to ret_from_syscall()
+	mov.l	r0, @(OFF_R0,r15)		! save the return value
+	mov.l	__syscall_trace, r1
+	mova	SYMBOL_NAME(ret_from_syscall), r0
+	jmp	@r1    	! Call syscall_trace() which notifies superior
+	 lds	r0, pr    	! Then return to ret_from_syscall()
 
 
 
@@ -396,41 +418,41 @@
 ! Handle old ABI system call.
 ! Note that ptrace(SYSCALL) is not supported for the old ABI.
 ! At this point:
-!   $r0, $r4-7 as per ABI
-!   $r8  = value of TRA register (= num_args<<2)
-!   $r14 = points to SYSCALL_NR in stack frame
+!   r0, r4-7 as per ABI
+!   r8  = value of TRA register (= num_args<<2)
+!   r14 = points to SYSCALL_NR in stack frame
 old_abi_system_call:
-	mov 	$r0, $r9    	    	! Save system call number in $r9
+	mov 	r0, r9    	    	! Save system call number in r9
 	!   	    	    	    	! arrange for return which pops stack
-	mov.l	__old_abi_syscall_ret, $r10
-	lds	$r10, $pr
+	mov.l	__old_abi_syscall_ret, r10
+	lds	r10, pr
 	!				  Build the stack frame if TRA > 0
-	mov	$r8, $r10
-	cmp/pl	$r10
+	mov	r8, r10
+	cmp/pl	r10
 	bf	0f
-	mov.l	@(SP,$r15), $r0		! get original user stack
-7:	add	#-4, $r10
-4:	mov.l	@($r0,$r10), $r1	! May cause address error exception..
-	mov.l	$r1, @-$r15
-	cmp/pl	$r10
+	mov.l	@(OFF_SP,r15), r0	! get original user stack
+7:	add	#-4, r10
+4:	mov.l	@(r0,r10), r1	! May cause address error exception..
+	mov.l	r1, @-r15
+	cmp/pl	r10
 	bt	7b
 0:
-	mov.l	$r9, @$r14	    	! set syscall_nr
+	mov.l	r9, @r14	    	! set syscall_nr
 	STI()
 	!   	    	    Call the system call handler through the table.
 	!   	    	    First check for bad syscall number
-	mov.l	__n_sys, $r10
-	cmp/hs	$r10, $r9
+	mov.l	__n_sys, r10
+	cmp/hs	r10, r9
 	bf	2f
 	!   	    	    Bad syscall number
 	rts			! return to old_abi_syscall_ret
-    	 mov	#-ENOSYS, $r0
+    	 mov	#-ENOSYS, r0
 	!   	    	    Good syscall number
-2:	shll2	$r9		! x4
-	mov.l	__sct, $r11
-	add	$r11, $r9
-	mov.l	@$r9, $r11
-	jmp	@$r11	    	! call specific syscall handler,
+2:	shll2	r9		! x4
+	mov.l	__sct, r11
+	add	r11, r9
+	mov.l	@r9, r11
+	jmp	@r11	    	! call specific syscall handler,
 	 nop
 
     	.align 2
@@ -440,16 +462,16 @@
     	! This code gets called on address error exception when copying
 	! syscall arguments from user stack to kernel stack.  It is
 	! supposed to return -EINVAL through old_abi_syscall_ret, but it
-	! appears to have been broken for a long time in that the $r0
-	! return value will be saved into the kernel stack relative to $r15
-	! but the value of $r15 is not correct partway through the loop.
-	! So the user prog is returned its old $r0 value, not -EINVAL.
+	! appears to have been broken for a long time in that the r0
+	! return value will be saved into the kernel stack relative to r15
+	! but the value of r15 is not correct partway through the loop.
+	! So the user prog is returned its old r0 value, not -EINVAL.
 	! Greg Banks 28 Aug 2000.
 	.section	.fixup,"ax"
 fixup_syscall_argerr:
-    	! First get $r15 back to 
+    	! First get r15 back to 
 	rts
-    	 mov	#-EINVAL, $r0
+    	 mov	#-EINVAL, r0
     	.previous
 
 	.section	__ex_table, "a"
@@ -473,18 +495,18 @@
 
 	.align	2
 reschedule:
-	mova	SYMBOL_NAME(ret_from_syscall), $r0
-	mov.l	1f, $r1
-	jmp	@$r1
-	 lds	$r0, $pr
+	mova	SYMBOL_NAME(ret_from_syscall), r0
+	mov.l	1f, r1
+	jmp	@r1
+	 lds	r0, pr
 	.align	2
 1:	.long	SYMBOL_NAME(schedule)
 
 ENTRY(ret_from_irq)
-	mov	#SR, $r0
-	mov.l	@($r0,$r15), $r0	! get status register
-	shll	$r0
-	shll	$r0		! kernel space?
+	mov	#OFF_SR, r0
+	mov.l	@(r0,r15), r0	! get status register
+	shll	r0
+	shll	r0		! kernel space?
 	bt	restore_all	! Yes, it's from kernel, go back soon
 	!
 	STI()
@@ -492,10 +514,10 @@
 	 nop
 
 ENTRY(ret_from_exception)
-	mov	#SR, $r0
-	mov.l	@($r0,$r15), $r0	! get status register
-	shll	$r0
-	shll	$r0		! kernel space?
+	mov	#OFF_SR, r0
+	mov.l	@(r0,r15), r0	! get status register
+	shll	r0
+	shll	r0		! kernel space?
 	bt	restore_all	! Yes, it's from kernel, go back soon
 	!
 	STI()
@@ -508,38 +530,38 @@
 	.align 2
 #ifdef COMPAT_OLD_SYSCALL_ABI
 old_abi_syscall_ret:
-	add	$r8, $r15	! pop off the arguments
+	add	r8, r15	! pop off the arguments
 	/* fall through */
 #endif
 syscall_ret:
-	mov.l	$r0, @(R0,$r15)	! save the return value
+	mov.l	r0, @(OFF_R0,r15)	! save the return value
 	/* fall through */
 
 ENTRY(ret_from_syscall)
-	mov.l	__irq_stat, $r0	! softirq_active
-	mov.l	@$r0, $r1
-	mov.l	@(4,$r0), $r2	! softirq_mask
-	tst	$r2, $r1
+	mov.l	__irq_stat, r0	! softirq_active
+	mov.l	@r0, r1
+	mov.l	@(4,r0), r2	! softirq_mask
+	tst	r2, r1
 	bt	ret_with_reschedule
 handle_softirq:
-	mov.l	__do_softirq, $r0
-	jsr	@$r0
+	mov.l	__do_softirq, r0
+	jsr	@r0
 	 nop
 ret_with_reschedule:
-	stc	$k_current, $r1
-	mov.l	@(need_resched,$r1), $r0
-	tst	#0xff, $r0
+	stc	k_current, r1
+	mov.l	@(need_resched,r1), r0
+	tst	#0xff, r0
 	bf	reschedule
-	mov.l	@(sigpending,$r1), $r0
-	tst	#0xff, $r0
+	mov.l	@(sigpending,r1), r0
+	tst	#0xff, r0
 	bt	restore_all
 signal_return:
-	mov	$r15, $r4
-	mov	#0, $r5
-	mov.l	__do_signal, $r1
-	mova	restore_all, $r0
-	jmp	@$r1
-	 lds	$r0, $pr
+	mov	r15, r4
+	mov	#0, r5
+	mov.l	__do_signal, r1
+	mova	restore_all, r0
+	jmp	@r1
+	 lds	r0, pr
 	.align	2
 __do_signal:
 	.long	SYMBOL_NAME(do_signal)
@@ -551,108 +573,108 @@
 	.align 2
 restore_all:
 #if defined(__SH4__)
-	mov.l	__fpu_prepare_fd, $r0
-	jsr	@$r0
-	 stc	$sr, $r4
-#endif
-	!
-	mov.l	@$r15+, $r0
-	mov.l	@$r15+, $r1
-	mov.l	@$r15+, $r2
-	mov.l	@$r15+, $r3
-	mov.l	@$r15+, $r4
-	mov.l	@$r15+, $r5
-	mov.l	@$r15+, $r6
-	mov.l	@$r15+, $r7
-	!
-	stc	$sr, $r8
-	mov.l	__blrb_flags, $r9	! BL =1, RB=1
-	or	$r9, $r8
-	ldc	$r8, $sr		! here, change the register bank
-	!
-	mov.l	@$r15+, $r8
-	mov.l	@$r15+, $r9
-	mov.l	@$r15+, $r10
-	mov.l	@$r15+, $r11
-	mov.l	@$r15+, $r12
-	mov.l	@$r15+, $r13
-	mov.l	@$r15+, $r14
-	mov.l	@$r15+, $k4	! original stack pointer
-	ldc.l	@$r15+, $spc
-	lds.l	@$r15+, $pr
-	mov.l	@$r15+, $k3	! original SR
-	ldc.l	@$r15+, $gbr
-	lds.l	@$r15+, $mach
-	lds.l	@$r15+, $macl
-	add	#4, $r15	! Skip syscall number
+	mov.l	__fpu_prepare_fd, r0
+	jsr	@r0
+	 stc	sr, r4
+#endif
+	!
+	mov.l	@r15+, r0
+	mov.l	@r15+, r1
+	mov.l	@r15+, r2
+	mov.l	@r15+, r3
+	mov.l	@r15+, r4
+	mov.l	@r15+, r5
+	mov.l	@r15+, r6
+	mov.l	@r15+, r7
+	!
+	stc	sr, r8
+	mov.l	__blrb_flags, r9	! BL =1, RB=1
+	or	r9, r8
+	ldc	r8, sr		! here, change the register bank
+	!
+	mov.l	@r15+, r8
+	mov.l	@r15+, r9
+	mov.l	@r15+, r10
+	mov.l	@r15+, r11
+	mov.l	@r15+, r12
+	mov.l	@r15+, r13
+	mov.l	@r15+, r14
+	mov.l	@r15+, k4	! original stack pointer
+	ldc.l	@r15+, spc
+	lds.l	@r15+, pr
+	mov.l	@r15+, k3	! original SR
+	ldc.l	@r15+, gbr
+	lds.l	@r15+, mach
+	lds.l	@r15+, macl
+	add	#4, r15	! Skip syscall number
 	!
 	! Calculate new SR value
-	mov	$k3, $k2	! original SR value
-	mov.l	1f, $k1
-	stc	$sr, $k0
-	and	$k1, $k0	! Get current FD-bit
-	mov.l	2f, $k1
-	and	$k1, $k2	! Mask orignal SR value
-	or	$k0, $k2	! Inherit current FD-bit
-	!
-	mov	$k3, $k0	! Calculate IMASK-bits
-	shlr2	$k0
-	and	#0x3c, $k0
-	cmp/eq	#0x3c, $k0
+	mov	k3, k2	! original SR value
+	mov.l	1f, k1
+	stc	sr, k0
+	and	k1, k0	! Get current FD-bit
+	mov.l	2f, k1
+	and	k1, k2	! Mask orignal SR value
+	or	k0, k2	! Inherit current FD-bit
+	!
+	mov	k3, k0	! Calculate IMASK-bits
+	shlr2	k0
+	and	#0x3c, k0
+	cmp/eq	#0x3c, k0
 	bt/s	7f
-	 shll2	$k0
-	mov	$g_imask, $k0
+	 shll2	k0
+	mov	g_imask, k0
 	!
-7:	or	$k0, $k2	! Set the IMASK-bits
-	ldc	$k2, $ssr
+7:	or	k0, k2	! Set the IMASK-bits
+	ldc	k2, ssr
 	!
 #if defined(__SH4__)
-	shll	$k2
-	shll	$k2
+	shll	k2
+	shll	k2
 	bf	9f		! user mode
 	/* Kernel to kernel transition */
-	mov.l	1f, $k1
-	tst	$k1, $k3
+	mov.l	1f, k1
+	tst	k1, k3
 	bf	9f		! it hadn't FPU
 	! Kernel to kernel and FPU was used
 	! There's the case we don't get FPU now
-	stc	$sr, $k2
-	tst	$k1, $k2
+	stc	sr, k2
+	tst	k1, k2
 	bt	8f
 	! We need to grab FPU here
-	xor	$k1, $k2
-	ldc	$k2, $sr		! Grab FPU
-	mov.l	__init_task_flags, $k1
-	mov.l	@$k1, $k2
-	mov.l	__PF_USEDFPU, $k0
-	or	$k0, $k2
-	mov.l	$k2, @$k1		! Set init_task.flags |= PF_USEDFPU
+	xor	k1, k2
+	ldc	k2, sr		! Grab FPU
+	mov.l	__init_task_flags, k1
+	mov.l	@k1, k2
+	mov.l	__PF_USEDFPU, k0
+	or	k0, k2
+	mov.l	k2, @k1		! Set init_task.flags |= PF_USEDFPU
 	!
 	! Restoring FPU...
 	!
-8:	mov.l	3f, $k1
-	lds	$k1, $fpscr
-	fmov.s	@$r15+, $fr0
-	fmov.s	@$r15+, $fr1
-	fmov.s	@$r15+, $fr2
-	fmov.s	@$r15+, $fr3
-	fmov.s	@$r15+, $fr4
-	fmov.s	@$r15+, $fr5
-	fmov.s	@$r15+, $fr6
-	fmov.s	@$r15+, $fr7
-	fmov.s	@$r15+, $fr8
-	fmov.s	@$r15+, $fr9
-	fmov.s	@$r15+, $fr10
-	fmov.s	@$r15+, $fr11
-	fmov.s	@$r15+, $fr12
-	fmov.s	@$r15+, $fr13
-	fmov.s	@$r15+, $fr14
-	fmov.s	@$r15+, $fr15
-	lds.l	@$r15+, $fpscr
-	lds.l	@$r15+, $fpul
+8:	mov.l	3f, k1
+	lds	k1, fpscr
+	fmov.s	@r15+, fr0
+	fmov.s	@r15+, fr1
+	fmov.s	@r15+, fr2
+	fmov.s	@r15+, fr3
+	fmov.s	@r15+, fr4
+	fmov.s	@r15+, fr5
+	fmov.s	@r15+, fr6
+	fmov.s	@r15+, fr7
+	fmov.s	@r15+, fr8
+	fmov.s	@r15+, fr9
+	fmov.s	@r15+, fr10
+	fmov.s	@r15+, fr11
+	fmov.s	@r15+, fr12
+	fmov.s	@r15+, fr13
+	fmov.s	@r15+, fr14
+	fmov.s	@r15+, fr15
+	lds.l	@r15+, fpscr
+	lds.l	@r15+, fpul
 9:
 #endif
-	mov	$k4, $r15
+	mov	k4, r15
 	rte
 	 nop
 
@@ -680,10 +702,10 @@
 !
 	.balign 	256,0,256
 general_exception:
-	mov.l	1f, $k2
-	mov.l	2f, $k3
+	mov.l	1f, k2
+	mov.l	2f, k3
 	bra	handle_exception
-	 mov.l	@$k2, $k2
+	 mov.l	@k2, k2
 	.align	2
 2:	.long	SYMBOL_NAME(ret_from_exception)
 1:	.long	EXPEVT
@@ -691,17 +713,17 @@
 !
 	.balign 	1024,0,1024
 tlb_miss:
-	mov.l	1f, $k2
-	mov.l	4f, $k3
+	mov.l	1f, k2
+	mov.l	4f, k3
 	bra	handle_exception
-	 mov.l	@$k2, $k2
+	 mov.l	@k2, k2
 !
 	.balign 	512,0,512
 interrupt:
-	mov.l	2f, $k2
-	mov.l	3f, $k3
+	mov.l	2f, k2
+	mov.l	3f, k3
 	bra	handle_exception
-	 mov.l	@$k2, $k2
+	 mov.l	@k2, k2
 
 	.align	2
 1:	.long	EXPEVT
@@ -715,102 +737,102 @@
 	! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
 	! save all registers onto stack.
 	!
-	stc	$ssr, $k0	! from kernel space?
-	shll	$k0		! Check MD bit (bit30) by shifting it into the T bit
-	shll	$k0
+	stc	ssr, k0	! from kernel space?
+	shll	k0		! Check MD bit (bit30) by shifting it into the T bit
+	shll	k0
 #if defined(__SH4__)
 	bf/s	8f		! it's from user to kernel transition
-	 mov	$r15, $k0	! save original stack to k0
+	 mov	r15, k0	! save original stack to k0
 	/* It's a kernel to kernel transition. */
 	/* Is the FPU disabled? */
-	mov.l	2f, $k1
-	stc	$ssr, $k0
-	tst	$k1, $k0
-	mov.l	4f, $k1
+	mov.l	2f, k1
+	stc	ssr, k0
+	tst	k1, k0
+	mov.l	4f, k1
 	bf/s	9f		! FPU is not enabled, no need to save it
-	 mov	$r15, $k0	! save original stack to k0
+	 mov	r15, k0	! save original stack to k0
 	! FPU is enabled, save it
 	! /* XXX: Need to save another bank of FPU if all FPU feature is used */
 	! /* Currently it's not the case for GCC (only udivsi3_i4, divsi3_i4) */
-	sts.l	$fpul,  @-$r15
-	sts.l	$fpscr, @-$r15
-	mov.l	6f, $k1
-	lds	$k1, $fpscr
-	mov.l	3f, $k1
-	fmov.s	$fr15, @-$r15
-	fmov.s	$fr14, @-$r15
-	fmov.s	$fr13, @-$r15
-	fmov.s	$fr12, @-$r15
-	fmov.s	$fr11, @-$r15
-	fmov.s	$fr10, @-$r15
-	fmov.s	$fr9, @-$r15
-	fmov.s	$fr8, @-$r15
-	fmov.s	$fr7, @-$r15
-	fmov.s	$fr6, @-$r15
-	fmov.s	$fr5, @-$r15
-	fmov.s	$fr4, @-$r15
-	fmov.s	$fr3, @-$r15
-	fmov.s	$fr2, @-$r15
-	fmov.s	$fr1, @-$r15
+	sts.l	fpul,  @-r15
+	sts.l	fpscr, @-r15
+	mov.l	6f, k1
+	lds	k1, fpscr
+	mov.l	3f, k1
+	fmov.s	fr15, @-r15
+	fmov.s	fr14, @-r15
+	fmov.s	fr13, @-r15
+	fmov.s	fr12, @-r15
+	fmov.s	fr11, @-r15
+	fmov.s	fr10, @-r15
+	fmov.s	fr9, @-r15
+	fmov.s	fr8, @-r15
+	fmov.s	fr7, @-r15
+	fmov.s	fr6, @-r15
+	fmov.s	fr5, @-r15
+	fmov.s	fr4, @-r15
+	fmov.s	fr3, @-r15
+	fmov.s	fr2, @-r15
+	fmov.s	fr1, @-r15
 	bra 9f
-	 fmov.s	$fr0, @-$r15
+	 fmov.s	fr0, @-r15
 #else
-	mov.l	3f, $k1
+	mov.l	3f, k1
 	bt/s	9f		! it's a kernel to kernel transition, and skip the FPU save.
-	 mov	$r15, $k0	! save original stack to k0 anyway
+	 mov	r15, k0	! save original stack to k0 anyway
 #endif
 8:	/* User space to kernel */
-	mov	#0x20, $k1
-	shll8	$k1			! $k1 <= 8192 == THREAD_SIZE
-	add	$current, $k1
-	mov	$k1, $r15		! change to kernel stack
+	mov	#0x20, k1
+	shll8	k1			! k1 <= 8192 == THREAD_SIZE
+	add	current, k1
+	mov	k1, r15		! change to kernel stack
 	!
-	mov.l	4f, $k1			! let kernel release FPU
+	mov.l	4f, k1			! let kernel release FPU
 9:	! Save the user registers on the stack.
 	! At this point, k1 should have been set to the new SR value
-  	mov	#-1, $k4
-	mov.l	$k4, @-$r15		! syscall_nr (default: -1)
+  	mov	#-1, k4
+	mov.l	k4, @-r15		! syscall_nr (default: -1)
 	!
-	sts.l	$macl, @-$r15
-	sts.l	$mach, @-$r15
-	stc.l	$gbr, @-$r15
-	stc.l	$ssr, @-$r15
-	sts.l	$pr, @-$r15
-	stc.l	$spc, @-$r15
-	!
-	lds	$k3, $pr		! Set the return address to pr
-	!
-	mov.l	$k0, @-$r15	! save orignal stack
-	mov.l	$r14, @-$r15
-	mov.l	$r13, @-$r15
-	mov.l	$r12, @-$r15
-	mov.l	$r11, @-$r15
-	mov.l	$r10, @-$r15
-	mov.l	$r9, @-$r15
-	mov.l	$r8, @-$r15
-	!
-	stc	$sr, $r8	! Back to normal register bank, and
-	or	$k1, $r8	! Block all interrupts, may release FPU
-	mov.l	5f, $k1
-	and	$k1, $r8	! ...
-	ldc	$r8, $sr	! ...changed here.
-	!
-	mov.l	$r7, @-$r15
-	mov.l	$r6, @-$r15
-	mov.l	$r5, @-$r15
-	mov.l	$r4, @-$r15
-	mov.l	$r3, @-$r15
-	mov.l	$r2, @-$r15
-	mov.l	$r1, @-$r15
-	mov.l	$r0, @-$r15
+	sts.l	macl, @-r15
+	sts.l	mach, @-r15
+	stc.l	gbr, @-r15
+	stc.l	ssr, @-r15
+	sts.l	pr, @-r15
+	stc.l	spc, @-r15
+	!
+	lds	k3, pr		! Set the return address to pr
+	!
+	mov.l	k0, @-r15	! save orignal stack
+	mov.l	r14, @-r15
+	mov.l	r13, @-r15
+	mov.l	r12, @-r15
+	mov.l	r11, @-r15
+	mov.l	r10, @-r15
+	mov.l	r9, @-r15
+	mov.l	r8, @-r15
+	!
+	stc	sr, r8	! Back to normal register bank, and
+	or	k1, r8	! Block all interrupts, may release FPU
+	mov.l	5f, k1
+	and	k1, r8	! ...
+	ldc	r8, sr	! ...changed here.
+	!
+	mov.l	r7, @-r15
+	mov.l	r6, @-r15
+	mov.l	r5, @-r15
+	mov.l	r4, @-r15
+	mov.l	r3, @-r15
+	mov.l	r2, @-r15
+	mov.l	r1, @-r15
+	mov.l	r0, @-r15
 	! Then, dispatch to the handler, according to the exception code.
-	stc	$k_ex_code, $r8
-	shlr2	$r8
-	shlr	$r8
-	mov.l	1f, $r9
-	add	$r8, $r9
-	mov.l	@$r9, $r9
-	jmp	@$r9
+	stc	k_ex_code, r8
+	shlr2	r8
+	shlr	r8
+	mov.l	1f, r9
+	add	r8, r9
+	mov.l	@r9, r9
+	jmp	@r9
 	 nop
 	.align	2
 1:	.long	SYMBOL_NAME(exception_handling_table)
@@ -833,8 +855,8 @@
 	.long	initial_page_write
 	.long	tlb_protection_violation_load
 	.long	tlb_protection_violation_store
-	.long	error	! address_error_load        (filled by trap_init)
-	.long	error	! address_error_store       (filled by trap_init)
+	.long	address_error_load
+	.long	address_error_store
 #if defined(__SH4__)
 	.long	SYMBOL_NAME(do_fpu_error)
 #else
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/fpu.c linux/arch/sh/kernel/fpu.c
--- v2.4.0/linux/arch/sh/kernel/fpu.c	Mon Apr 24 13:54:17 2000
+++ linux/arch/sh/kernel/fpu.c	Sun Jan 28 18:56:00 2001
@@ -21,43 +21,43 @@
 void
 save_fpu(struct task_struct *tsk)
 {
-	asm volatile("sts.l	$fpul, @-%0\n\t"
-		     "sts.l	$fpscr, @-%0\n\t"
-		     "lds	%1, $fpscr\n\t"
+	asm volatile("sts.l	fpul, @-%0\n\t"
+		     "sts.l	fpscr, @-%0\n\t"
+		     "lds	%1, fpscr\n\t"
 		     "frchg\n\t"
-		     "fmov.s	$fr15, @-%0\n\t"
-		     "fmov.s	$fr14, @-%0\n\t"
-		     "fmov.s	$fr13, @-%0\n\t"
-		     "fmov.s	$fr12, @-%0\n\t"
-		     "fmov.s	$fr11, @-%0\n\t"
-		     "fmov.s	$fr10, @-%0\n\t"
-		     "fmov.s	$fr9, @-%0\n\t"
-		     "fmov.s	$fr8, @-%0\n\t"
-		     "fmov.s	$fr7, @-%0\n\t"
-		     "fmov.s	$fr6, @-%0\n\t"
-		     "fmov.s	$fr5, @-%0\n\t"
-		     "fmov.s	$fr4, @-%0\n\t"
-		     "fmov.s	$fr3, @-%0\n\t"
-		     "fmov.s	$fr2, @-%0\n\t"
-		     "fmov.s	$fr1, @-%0\n\t"
-		     "fmov.s	$fr0, @-%0\n\t"
+		     "fmov.s	fr15, @-%0\n\t"
+		     "fmov.s	fr14, @-%0\n\t"
+		     "fmov.s	fr13, @-%0\n\t"
+		     "fmov.s	fr12, @-%0\n\t"
+		     "fmov.s	fr11, @-%0\n\t"
+		     "fmov.s	fr10, @-%0\n\t"
+		     "fmov.s	fr9, @-%0\n\t"
+		     "fmov.s	fr8, @-%0\n\t"
+		     "fmov.s	fr7, @-%0\n\t"
+		     "fmov.s	fr6, @-%0\n\t"
+		     "fmov.s	fr5, @-%0\n\t"
+		     "fmov.s	fr4, @-%0\n\t"
+		     "fmov.s	fr3, @-%0\n\t"
+		     "fmov.s	fr2, @-%0\n\t"
+		     "fmov.s	fr1, @-%0\n\t"
+		     "fmov.s	fr0, @-%0\n\t"
 		     "frchg\n\t"
-		     "fmov.s	$fr15, @-%0\n\t"
-		     "fmov.s	$fr14, @-%0\n\t"
-		     "fmov.s	$fr13, @-%0\n\t"
-		     "fmov.s	$fr12, @-%0\n\t"
-		     "fmov.s	$fr11, @-%0\n\t"
-		     "fmov.s	$fr10, @-%0\n\t"
-		     "fmov.s	$fr9, @-%0\n\t"
-		     "fmov.s	$fr8, @-%0\n\t"
-		     "fmov.s	$fr7, @-%0\n\t"
-		     "fmov.s	$fr6, @-%0\n\t"
-		     "fmov.s	$fr5, @-%0\n\t"
-		     "fmov.s	$fr4, @-%0\n\t"
-		     "fmov.s	$fr3, @-%0\n\t"
-		     "fmov.s	$fr2, @-%0\n\t"
-		     "fmov.s	$fr1, @-%0\n\t"
-		     "fmov.s	$fr0, @-%0"
+		     "fmov.s	fr15, @-%0\n\t"
+		     "fmov.s	fr14, @-%0\n\t"
+		     "fmov.s	fr13, @-%0\n\t"
+		     "fmov.s	fr12, @-%0\n\t"
+		     "fmov.s	fr11, @-%0\n\t"
+		     "fmov.s	fr10, @-%0\n\t"
+		     "fmov.s	fr9, @-%0\n\t"
+		     "fmov.s	fr8, @-%0\n\t"
+		     "fmov.s	fr7, @-%0\n\t"
+		     "fmov.s	fr6, @-%0\n\t"
+		     "fmov.s	fr5, @-%0\n\t"
+		     "fmov.s	fr4, @-%0\n\t"
+		     "fmov.s	fr3, @-%0\n\t"
+		     "fmov.s	fr2, @-%0\n\t"
+		     "fmov.s	fr1, @-%0\n\t"
+		     "fmov.s	fr0, @-%0"
 		     : /* no output */
 		     : "r" ((char *)(&tsk->thread.fpu.hard.status)),
 		       "r" (FPSCR_INIT)
@@ -70,43 +70,43 @@
 static void
 restore_fpu(struct task_struct *tsk)
 {
-	asm volatile("lds	%1, $fpscr\n\t"
-		     "fmov.s	@%0+, $fr0\n\t"
-		     "fmov.s	@%0+, $fr1\n\t"
-		     "fmov.s	@%0+, $fr2\n\t"
-		     "fmov.s	@%0+, $fr3\n\t"
-		     "fmov.s	@%0+, $fr4\n\t"
-		     "fmov.s	@%0+, $fr5\n\t"
-		     "fmov.s	@%0+, $fr6\n\t"
-		     "fmov.s	@%0+, $fr7\n\t"
-		     "fmov.s	@%0+, $fr8\n\t"
-		     "fmov.s	@%0+, $fr9\n\t"
-		     "fmov.s	@%0+, $fr10\n\t"
-		     "fmov.s	@%0+, $fr11\n\t"
-		     "fmov.s	@%0+, $fr12\n\t"
-		     "fmov.s	@%0+, $fr13\n\t"
-		     "fmov.s	@%0+, $fr14\n\t"
-		     "fmov.s	@%0+, $fr15\n\t"
+	asm volatile("lds	%1, fpscr\n\t"
+		     "fmov.s	@%0+, fr0\n\t"
+		     "fmov.s	@%0+, fr1\n\t"
+		     "fmov.s	@%0+, fr2\n\t"
+		     "fmov.s	@%0+, fr3\n\t"
+		     "fmov.s	@%0+, fr4\n\t"
+		     "fmov.s	@%0+, fr5\n\t"
+		     "fmov.s	@%0+, fr6\n\t"
+		     "fmov.s	@%0+, fr7\n\t"
+		     "fmov.s	@%0+, fr8\n\t"
+		     "fmov.s	@%0+, fr9\n\t"
+		     "fmov.s	@%0+, fr10\n\t"
+		     "fmov.s	@%0+, fr11\n\t"
+		     "fmov.s	@%0+, fr12\n\t"
+		     "fmov.s	@%0+, fr13\n\t"
+		     "fmov.s	@%0+, fr14\n\t"
+		     "fmov.s	@%0+, fr15\n\t"
 		     "frchg\n\t"
-		     "fmov.s	@%0+, $fr0\n\t"
-		     "fmov.s	@%0+, $fr1\n\t"
-		     "fmov.s	@%0+, $fr2\n\t"
-		     "fmov.s	@%0+, $fr3\n\t"
-		     "fmov.s	@%0+, $fr4\n\t"
-		     "fmov.s	@%0+, $fr5\n\t"
-		     "fmov.s	@%0+, $fr6\n\t"
-		     "fmov.s	@%0+, $fr7\n\t"
-		     "fmov.s	@%0+, $fr8\n\t"
-		     "fmov.s	@%0+, $fr9\n\t"
-		     "fmov.s	@%0+, $fr10\n\t"
-		     "fmov.s	@%0+, $fr11\n\t"
-		     "fmov.s	@%0+, $fr12\n\t"
-		     "fmov.s	@%0+, $fr13\n\t"
-		     "fmov.s	@%0+, $fr14\n\t"
-		     "fmov.s	@%0+, $fr15\n\t"
+		     "fmov.s	@%0+, fr0\n\t"
+		     "fmov.s	@%0+, fr1\n\t"
+		     "fmov.s	@%0+, fr2\n\t"
+		     "fmov.s	@%0+, fr3\n\t"
+		     "fmov.s	@%0+, fr4\n\t"
+		     "fmov.s	@%0+, fr5\n\t"
+		     "fmov.s	@%0+, fr6\n\t"
+		     "fmov.s	@%0+, fr7\n\t"
+		     "fmov.s	@%0+, fr8\n\t"
+		     "fmov.s	@%0+, fr9\n\t"
+		     "fmov.s	@%0+, fr10\n\t"
+		     "fmov.s	@%0+, fr11\n\t"
+		     "fmov.s	@%0+, fr12\n\t"
+		     "fmov.s	@%0+, fr13\n\t"
+		     "fmov.s	@%0+, fr14\n\t"
+		     "fmov.s	@%0+, fr15\n\t"
 		     "frchg\n\t"
-		     "lds.l	@%0+, $fpscr\n\t"
-		     "lds.l	@%0+, $fpul\n\t"
+		     "lds.l	@%0+, fpscr\n\t"
+		     "lds.l	@%0+, fpul\n\t"
 		     : /* no output */
 		     : "r" (&tsk->thread.fpu), "r" (FPSCR_INIT)
 		     : "memory");
@@ -120,41 +120,41 @@
 
 void fpu_init(void)
 {
-	asm volatile("lds	%0, $fpul\n\t"
-		     "lds	%1, $fpscr\n\t"
-		     "fsts	$fpul, $fr0\n\t"
-		     "fsts	$fpul, $fr1\n\t"
-		     "fsts	$fpul, $fr2\n\t"
-		     "fsts	$fpul, $fr3\n\t"
-		     "fsts	$fpul, $fr4\n\t"
-		     "fsts	$fpul, $fr5\n\t"
-		     "fsts	$fpul, $fr6\n\t"
-		     "fsts	$fpul, $fr7\n\t"
-		     "fsts	$fpul, $fr8\n\t"
-		     "fsts	$fpul, $fr9\n\t"
-		     "fsts	$fpul, $fr10\n\t"
-		     "fsts	$fpul, $fr11\n\t"
-		     "fsts	$fpul, $fr12\n\t"
-		     "fsts	$fpul, $fr13\n\t"
-		     "fsts	$fpul, $fr14\n\t"
-		     "fsts	$fpul, $fr15\n\t"
+	asm volatile("lds	%0, fpul\n\t"
+		     "lds	%1, fpscr\n\t"
+		     "fsts	fpul, fr0\n\t"
+		     "fsts	fpul, fr1\n\t"
+		     "fsts	fpul, fr2\n\t"
+		     "fsts	fpul, fr3\n\t"
+		     "fsts	fpul, fr4\n\t"
+		     "fsts	fpul, fr5\n\t"
+		     "fsts	fpul, fr6\n\t"
+		     "fsts	fpul, fr7\n\t"
+		     "fsts	fpul, fr8\n\t"
+		     "fsts	fpul, fr9\n\t"
+		     "fsts	fpul, fr10\n\t"
+		     "fsts	fpul, fr11\n\t"
+		     "fsts	fpul, fr12\n\t"
+		     "fsts	fpul, fr13\n\t"
+		     "fsts	fpul, fr14\n\t"
+		     "fsts	fpul, fr15\n\t"
 		     "frchg\n\t"
-		     "fsts	$fpul, $fr0\n\t"
-		     "fsts	$fpul, $fr1\n\t"
-		     "fsts	$fpul, $fr2\n\t"
-		     "fsts	$fpul, $fr3\n\t"
-		     "fsts	$fpul, $fr4\n\t"
-		     "fsts	$fpul, $fr5\n\t"
-		     "fsts	$fpul, $fr6\n\t"
-		     "fsts	$fpul, $fr7\n\t"
-		     "fsts	$fpul, $fr8\n\t"
-		     "fsts	$fpul, $fr9\n\t"
-		     "fsts	$fpul, $fr10\n\t"
-		     "fsts	$fpul, $fr11\n\t"
-		     "fsts	$fpul, $fr12\n\t"
-		     "fsts	$fpul, $fr13\n\t"
-		     "fsts	$fpul, $fr14\n\t"
-		     "fsts	$fpul, $fr15\n\t"
+		     "fsts	fpul, fr0\n\t"
+		     "fsts	fpul, fr1\n\t"
+		     "fsts	fpul, fr2\n\t"
+		     "fsts	fpul, fr3\n\t"
+		     "fsts	fpul, fr4\n\t"
+		     "fsts	fpul, fr5\n\t"
+		     "fsts	fpul, fr6\n\t"
+		     "fsts	fpul, fr7\n\t"
+		     "fsts	fpul, fr8\n\t"
+		     "fsts	fpul, fr9\n\t"
+		     "fsts	fpul, fr10\n\t"
+		     "fsts	fpul, fr11\n\t"
+		     "fsts	fpul, fr12\n\t"
+		     "fsts	fpul, fr13\n\t"
+		     "fsts	fpul, fr14\n\t"
+		     "fsts	fpul, fr15\n\t"
 		     "frchg"
 		     : /* no output */
 		     : "r" (0), "r" (FPSCR_INIT));
@@ -192,9 +192,9 @@
 			 *
 			 * There's race condition in __cli:
 			 *
-			 *   (1) $SR --> register
+			 *   (1) SR --> register
 			 *   (2) Set IMASK of register
-			 *   (3) $SR <-- register
+			 *   (3) SR <-- register
 			 *
 			 * Between (1) and (2), or (2) and (3) getting
 			 * interrupt, and interrupt handler (or
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/head.S linux/arch/sh/kernel/head.S
--- v2.4.0/linux/arch/sh/kernel/head.S	Mon Oct  2 11:57:34 2000
+++ linux/arch/sh/kernel/head.S	Sun Jan 28 18:56:00 2001
@@ -37,40 +37,40 @@
  */
 ENTRY(_stext)
 	!			Initialize Status Register
-	mov.l	1f, $r0		! MD=1, RB=0, BL=0, IMASK=0xF
-	ldc	$r0, $sr
+	mov.l	1f, r0		! MD=1, RB=0, BL=0, IMASK=0xF
+	ldc	r0, sr
 	!			Initialize global interrupt mask
-	mov	#0, $r0
-	ldc	$r0, $r6_bank
+	mov	#0, r0
+	ldc	r0, r6_bank
 	!
-	mov.l	2f, $r0
-	mov	$r0, $r15	! Set initial r15 (stack pointer)
-	mov	#0x20, $r1	!
-	shll8	$r1		! $r1 = 8192
-	sub	$r1, $r0	!
-	ldc	$r0, $r7_bank	! ... and init_task
+	mov.l	2f, r0
+	mov	r0, r15		! Set initial r15 (stack pointer)
+	mov	#0x20, r1	!
+	shll8	r1		! r1 = 8192
+	sub	r1, r0		!
+	ldc	r0, r7_bank	! ... and init_task
 	!
 #if defined(__SH4__)
 	!                       Initialize fpu
-	mov.l   7f, $r0
-	jsr     @$r0
+	mov.l   7f, r0
+	jsr     @r0
 	 nop
 #endif
 	!			Enable cache
-	mov.l	6f, $r0
-	jsr	@$r0
+	mov.l	6f, r0
+	jsr	@r0
 	 nop
 	!			Clear BSS area
-	mov.l	3f, $r1
-	add	#4, $r1
-	mov.l	4f, $r2
-	mov	#0, $r0
-9:	cmp/hs	$r2, $r1
+	mov.l	3f, r1
+	add	#4, r1
+	mov.l	4f, r2
+	mov	#0, r0
+9:	cmp/hs	r2, r1
 	bf/s	9b		! while (r1 < r2)
-	 mov.l	$r0,@-$r2
+	 mov.l	r0,@-r2
 	!			Start kernel
-	mov.l	5f, $r0
-	jmp	@$r0
+	mov.l	5f, r0
+	jmp	@r0
 	 nop
 
 	.balign 4
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c
--- v2.4.0/linux/arch/sh/kernel/irq.c	Wed Aug  9 13:59:04 2000
+++ linux/arch/sh/kernel/irq.c	Sun Jan 28 18:56:00 2001
@@ -235,7 +235,7 @@
 	unsigned int status;
 
 	/* Get IRQ number */
-	asm volatile("stc	$r2_bank, %0\n\t"
+	asm volatile("stc	r2_bank, %0\n\t"
 		     "shlr2	%0\n\t"
 		     "shlr2	%0\n\t"
 		     "shlr	%0\n\t"
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/irq_imask.c linux/arch/sh/kernel/irq_imask.c
--- v2.4.0/linux/arch/sh/kernel/irq_imask.c	Mon Oct  2 11:57:34 2000
+++ linux/arch/sh/kernel/irq_imask.c	Sun Jan 28 18:56:00 2001
@@ -59,16 +59,16 @@
 {
 	unsigned long __dummy;
 
-	asm volatile("ldc	%2, $r6_bank\n\t"
-		     "stc	$sr, %0\n\t"
+	asm volatile("ldc	%2, r6_bank\n\t"
+		     "stc	sr, %0\n\t"
 		     "and	#0xf0, %0\n\t"
 		     "shlr2	%0\n\t"
 		     "cmp/eq	#0x3c, %0\n\t"
 		     "bt/s	1f	! CLI-ed\n\t"
-		     " stc	$sr, %0\n\t"
+		     " stc	sr, %0\n\t"
 		     "and	%1, %0\n\t"
 		     "or	%2, %0\n\t"
-		     "ldc	%0, $sr\n"
+		     "ldc	%0, sr\n"
 		     "1:"
 		     : "=&z" (__dummy)
 		     : "r" (~0xf0), "r" (ip << 4)
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c
--- v2.4.0/linux/arch/sh/kernel/process.c	Mon Oct  2 11:57:34 2000
+++ linux/arch/sh/kernel/process.c	Sun Jan 28 18:56:00 2001
@@ -14,6 +14,8 @@
 #define __KERNEL_SYSCALLS__
 #include <stdarg.h>
 
+#include <linux/config.h>
+
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -31,6 +33,7 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -39,8 +42,9 @@
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 #include <asm/elf.h>
-
-#include <linux/irq.h>
+#ifdef CONFIG_SH_STANDARD_BIOS
+#include <asm/sh_bios.h>
+#endif
 
 static int hlt_counter=0;
 
@@ -79,11 +83,17 @@
 }
 
 void machine_restart(char * __unused)
-{ /* Need to set MMU_TTB?? */
+{
+#ifdef CONFIG_SH_STANDARD_BIOS
+	sh_bios_shutdown(1);
+#endif
 }
 
 void machine_halt(void)
 {
+#ifdef CONFIG_SH_STANDARD_BIOS
+	sh_bios_shutdown(0);
+#endif
 }
 
 void machine_power_off(void)
@@ -93,7 +103,7 @@
 void show_regs(struct pt_regs * regs)
 {
 	printk("\n");
-	printk("PC  : %08lx SP  : %08lx SR  : %08lx TEA : %08lx\n",
+	printk("PC  : %08lx SP  : %08lx SR  : %08lx TEA : %08x\n",
 	       regs->pc, regs->regs[15], regs->sr, ctrl_inl(MMU_TEA));
 	printk("R0  : %08lx R1  : %08lx R2  : %08lx R3  : %08lx\n",
 	       regs->regs[0],regs->regs[1],
@@ -144,12 +154,12 @@
 	register unsigned long __sc9 __asm__ ("r9") = (long) fn;
 
 	__asm__("trapa	#0x12\n\t" 	/* Linux/SH system call */
-		"tst	#0xff, $r0\n\t"	/* child or parent? */
+		"tst	#0xff, r0\n\t"	/* child or parent? */
 		"bf	1f\n\t"		/* parent - jump */
-		"jsr	@$r9\n\t"	/* call fn */
-		" mov	$r8, $r4\n\t"	/* push argument */
-		"mov	$r0, $r4\n\t"	/* return value to arg of exit */
-		"mov	%1, $r3\n\t"	/* exit */
+		"jsr	@r9\n\t"	/* call fn */
+		" mov	r8, r4\n\t"	/* push argument */
+		"mov	r0, r4\n\t"	/* return value to arg of exit */
+		"mov	%1, r3\n\t"	/* exit */
 		"trapa	#0x11\n"
 		"1:"
 		: "=z" (__sc0)
@@ -285,7 +295,7 @@
 	 * Restore the kernel mode register
 	 *   	k7 (r7_bank1)
 	 */
-	asm volatile("ldc	%0, $r7_bank"
+	asm volatile("ldc	%0, r7_bank"
 		     : /* no output */
 		     :"r" (next));
 }
@@ -376,7 +386,7 @@
 asmlinkage void print_syscall(int x)
 {
 	unsigned long flags, sr;
-	asm("stc	$sr, %0": "=r" (sr));
+	asm("stc	sr, %0": "=r" (sr));
 	save_and_cli(flags);
 	printk("%c: %c %c, %c: SYSCALL\n", (x&63)+32,
 	       (current->flags&PF_USEDFPU)?'C':' ',
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c
--- v2.4.0/linux/arch/sh/kernel/setup.c	Thu Jan  4 13:19:13 2001
+++ linux/arch/sh/kernel/setup.c	Sun Jan 28 18:56:00 2001
@@ -503,8 +503,8 @@
 		       "cache size\t: 8K-byte/16K-byte\n");
 #endif
 	p += sprintf(p, "bogomips\t: %lu.%02lu\n\n",
-		     (loops_per_jiffy+2500)/(500000/HZ),
-		     ((loops_per_jiffy+2500)/(5000/HZ)) % 100);
+		     loops_per_jiffy/(500000/HZ),
+		     (loops_per_jiffy/(5000/HZ)) % 100);
 	p += sprintf(p, "Machine: %s\n", sh_mv.mv_name);
 
 #define PRINT_CLOCK(name, value) \
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/sh_bios.c linux/arch/sh/kernel/sh_bios.c
--- v2.4.0/linux/arch/sh/kernel/sh_bios.c	Mon Oct  2 11:57:34 2000
+++ linux/arch/sh/kernel/sh_bios.c	Sun Jan 28 18:56:00 2001
@@ -1,4 +1,4 @@
-/* $Id: sh_bios.c,v 1.3 2000/09/30 03:43:30 gniibe Exp $
+/* $Id: sh_bios.c,v 1.5 2001/01/08 08:42:32 gniibe Exp $
  *
  *  linux/arch/sh/kernel/sh_bios.c
  *  C interface for trapping into the standard LinuxSH BIOS.
@@ -7,13 +7,12 @@
  *
  */
 
-#include <linux/config.h>
 #include <asm/sh_bios.h>
 
-#ifdef CONFIG_SH_STANDARD_BIOS
-
 #define BIOS_CALL_CONSOLE_WRITE     	0
-#define BIOS_CALL_READ_BLOCK     	1   	/* not implemented */
+#define BIOS_CALL_READ_BLOCK     	1
+#define BIOS_CALL_ETH_NODE_ADDR		10
+#define BIOS_CALL_SHUTDOWN		11
 #define BIOS_CALL_CHAR_OUT     	    	0x1f  	/* TODO: hack */
 #define BIOS_CALL_GDB_GET_MODE_PTR     	0xfe
 #define BIOS_CALL_GDB_DETACH     	0xff
@@ -66,5 +65,12 @@
     sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0);
 }
 
-#endif
+void sh_bios_get_node_addr (unsigned char *node_addr)
+{
+    sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0);
+}
 
+void sh_bios_shutdown(unsigned int how)
+{
+    sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0);
+}
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/sh_ksyms.c linux/arch/sh/kernel/sh_ksyms.c
--- v2.4.0/linux/arch/sh/kernel/sh_ksyms.c	Thu Jan  4 13:19:13 2001
+++ linux/arch/sh/kernel/sh_ksyms.c	Sun Jan 28 18:56:00 2001
@@ -64,10 +64,11 @@
 #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL_NOVERS(name)
  
 /* These symbols are generated by the compiler itself */
+DECLARE_EXPORT(__udivsi3);
+DECLARE_EXPORT(__sdivsi3);
+
 #ifdef __SH4__
  
-DECLARE_EXPORT(__udivsi3_i4);
-DECLARE_EXPORT(__sdivsi3_i4);
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
 DECLARE_EXPORT(__ashrdi3);
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/signal.c linux/arch/sh/kernel/signal.c
--- v2.4.0/linux/arch/sh/kernel/signal.c	Sun Sep  3 11:53:42 2000
+++ linux/arch/sh/kernel/signal.c	Sun Jan 28 18:56:00 2001
@@ -29,8 +29,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-			 int options, unsigned long *ru);
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
@@ -433,7 +431,7 @@
 		current->comm, current->pid, frame, regs->pc, regs->pr);
 #endif
 
-	flush_icache_range(regs->pr, regs->pr+4);
+	flush_cache_sigtramp(regs->pr);
 	return;
 
 give_sigsegv:
@@ -507,7 +505,7 @@
 		current->comm, current->pid, frame, regs->pc, regs->pr);
 #endif
 
-	flush_icache_range(regs->pr, regs->pr+4);
+	flush_cache_sigtramp(regs->pr);
 	return;
 
 give_sigsegv:
diff -u --recursive --new-file v2.4.0/linux/arch/sh/kernel/traps.c linux/arch/sh/kernel/traps.c
--- v2.4.0/linux/arch/sh/kernel/traps.c	Sun Dec  3 17:48:19 2000
+++ linux/arch/sh/kernel/traps.c	Sun Jan 28 18:56:00 2001
@@ -2,7 +2,9 @@
  *
  *  linux/arch/sh/traps.c
  *
- *  SuperH version: Copyright (C) 1999  Niibe Yutaka
+ *  SuperH version: Copyright (C) 1999 Niibe Yutaka
+ *                  Copyright (C) 2000 Philipp Rumpf
+ *                  Copyright (C) 2000 David Howells
  */
 
 /*
@@ -35,7 +37,7 @@
 { \
 	unsigned long error_code; \
  \
-	asm volatile("stc	$r2_bank, %0": "=r" (error_code)); \
+	asm volatile("stc	r2_bank, %0": "=r" (error_code)); \
 	sti(); \
 	tsk->thread.error_code = error_code; \
 	tsk->thread.trap_no = trapnr; \
@@ -69,7 +71,16 @@
 		die(str, regs, err);
 }
 
-static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
+static int handle_unaligned_notify_count = 10;
+
+/*
+ * try and fix up kernelspace address errors
+ * - userspace errors just cause EFAULT to be returned, resulting in SEGV
+ * - kernel/userspace interfaces cause a jump to an appropriate handler
+ * - other kernel errors are bad
+ * - return 0 if fixed-up, -EFAULT if non-fatal (to the kernel) fault
+ */
+static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
 {
 	if (!user_mode(regs))
 	{
@@ -77,14 +88,407 @@
 		fixup = search_exception_table(regs->pc);
 		if (fixup) {
 			regs->pc = fixup;
-			return;
+			return 0;
 		}
 		die(str, regs, err);
 	}
+	return -EFAULT;
+}
+
+/*
+ * handle an instruction that does an unaligned memory access by emulating the
+ * desired behaviour
+ * - note that PC _may not_ point to the faulting instruction
+ *   (if that instruction is in a branch delay slot)
+ * - return 0 if emulation okay, -EFAULT on existential error
+ */
+static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
+{
+	int ret, index, count;
+	unsigned long *rm, *rn;
+	unsigned char *src, *dst;
+
+	index = (instruction>>8)&15;	/* 0x0F00 */
+	rn = &regs->regs[index];
+
+	index = (instruction>>4)&15;	/* 0x00F0 */
+	rm = &regs->regs[index];
+
+	count = 1<<(instruction&3);
+
+	ret = -EFAULT;
+	switch (instruction>>12) {
+	case 0: /* mov.[bwl] to/from memory via r0+rn */
+		if (instruction & 8) {
+			/* from memory */
+			src = (unsigned char*) *rm;
+			src += regs->regs[0];
+			dst = (unsigned char*) rn;
+			*(unsigned long*)dst = 0;
+
+#ifdef __LITTLE_ENDIAN__
+			if (copy_from_user(dst, src, count))
+				goto fetch_fault;
+
+			if ((count == 2) && dst[1] & 0x80) {
+				dst[2] = 0xff;
+				dst[3] = 0xff;
+			}
+#else
+			dst += 4-count;
+
+			if (__copy_user(dst, src, count))
+				goto fetch_fault;
+
+			if ((count == 2) && dst[2] & 0x80) {
+				dst[0] = 0xff;
+				dst[1] = 0xff;
+			}
+#endif
+		} else {
+			/* to memory */
+			src = (unsigned char*) rm;
+#if !defined(__LITTLE_ENDIAN__)
+			src += 4-count;
+#endif
+			dst = (unsigned char*) *rn;
+			dst += regs->regs[0];
+
+			if (copy_to_user(dst, src, count))
+				goto fetch_fault;
+		}
+		ret = 0;
+		break;
+
+	case 1: /* mov.l Rm,@(disp,Rn) */
+		src = (unsigned char*) rm;
+		dst = (unsigned char*) *rn;
+		dst += (instruction&0x000F)<<2;
+
+		if (copy_to_user(dst,src,4))
+			goto fetch_fault;
+		ret = 0;
+ 		break;
+
+	case 2: /* mov.[bwl] to memory, possibly with pre-decrement */
+		if (instruction & 4)
+			*rn -= count;
+		src = (unsigned char*) rm;
+		dst = (unsigned char*) *rn;
+#if !defined(__LITTLE_ENDIAN__)
+		src += 4-count;
+#endif
+		if (copy_to_user(dst, src, count))
+			goto fetch_fault;
+		ret = 0;
+		break;
+
+	case 5: /* mov.l @(disp,Rm),Rn */
+		src = (unsigned char*) *rm;
+		src += (instruction&0x000F)<<2;
+		dst = (unsigned char*) rn;
+		*(unsigned long*)dst = 0;
+
+		if (copy_from_user(dst,src,4))
+			goto fetch_fault;
+		ret = 0;
+ 		break;
+
+	case 6:	/* mov.[bwl] from memory, possibly with post-increment */
+		src = (unsigned char*) *rm;
+		if (instruction & 4)
+			*rm += count;
+		dst = (unsigned char*) rn;
+		*(unsigned long*)dst = 0;
+		
+#ifdef __LITTLE_ENDIAN__
+		if (copy_from_user(dst, src, count))
+			goto fetch_fault;
+
+		if ((count == 2) && dst[1] & 0x80) {
+			dst[2] = 0xff;
+			dst[3] = 0xff;
+		}
+#else
+		dst += 4-count;
+		
+		if (copy_from_user(dst, src, count))
+			goto fetch_fault;
+
+		if ((count == 2) && dst[2] & 0x80) {
+			dst[0] = 0xff;
+			dst[1] = 0xff;
+		}
+#endif
+		ret = 0;
+		break;
+
+	case 8:
+		switch ((instruction&0xFF00)>>8) {
+		case 0x81: /* mov.w R0,@(disp,Rn) */
+			src = (unsigned char*) &regs->regs[0];
+#if !defined(__LITTLE_ENDIAN__)
+			src += 2;
+#endif
+			dst = (unsigned char*) *rm; /* called Rn in the spec */
+			dst += (instruction&0x000F)<<1;
+
+			if (copy_to_user(dst, src, 2))
+				goto fetch_fault;
+			ret = 0;
+			break;
+
+		case 0x85: /* mov.w @(disp,Rm),R0 */
+			src = (unsigned char*) *rm;
+			src += (instruction&0x000F)<<1;
+			dst = (unsigned char*) &regs->regs[0];
+			*(unsigned long*)dst = 0;
+
+#if !defined(__LITTLE_ENDIAN__)
+			dst += 2;
+#endif
+
+			if (copy_from_user(dst, src, 2))
+				goto fetch_fault;
+
+#ifdef __LITTLE_ENDIAN__
+			if (dst[1] & 0x80) {
+				dst[2] = 0xff;
+				dst[3] = 0xff;
+			}
+#else
+			if (dst[2] & 0x80) {
+				dst[0] = 0xff;
+				dst[1] = 0xff;
+			}
+#endif
+			ret = 0;
+			break;
+		}
+		break;
+	}
+	return ret;
+
+ fetch_fault:
+	/* Argh. Address not only misaligned but also non-existent.
+	 * Raise an EFAULT and see if it's trapped
+	 */
+	return die_if_no_fixup("Fault in unaligned fixup", regs, 0);
+}
+
+/*
+ * emulate the instruction in the delay slot
+ * - fetches the instruction from PC+2
+ */
+static inline int handle_unaligned_delayslot(struct pt_regs *regs)
+{
+	u16 instruction;
+
+	if (copy_from_user(&instruction, (u16 *)(regs->pc+2), 2)) {
+		/* the instruction-fetch faulted */
+		if (user_mode(regs))
+			return -EFAULT;
+
+		/* kernel */
+		die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0);
+	}
+
+	return handle_unaligned_ins(instruction,regs);
+}
+
+/*
+ * handle an instruction that does an unaligned memory access
+ * - have to be careful of branch delay-slot instructions that fault
+ *   - if the branch would be taken PC points to the branch
+ *   - if the branch would not be taken, PC points to delay-slot
+ * - return 0 if handled, -EFAULT if failed (may not return if in kernel)
+ */
+static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
+{
+	u_int rm;
+	int ret, index;
+
+	index = (instruction>>8)&15;	/* 0x0F00 */
+	rm = regs->regs[index];
+
+	/* shout about the first ten userspace fixups */
+	if (user_mode(regs) && handle_unaligned_notify_count>0) {
+	    handle_unaligned_notify_count--;
+
+	    printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+		   current->comm,current->pid,(u16*)regs->pc,instruction);
+	}
+
+	ret = -EFAULT;
+	switch (instruction&0xF000) {
+	case 0x0000:
+		if (instruction==0x000B) {
+			/* rts */
+			ret = handle_unaligned_delayslot(regs);
+			if (ret==0)
+				regs->pc = regs->pr;
+		}
+		else if ((instruction&0x00FF)==0x0023) {
+			/* braf @Rm */
+			ret = handle_unaligned_delayslot(regs);
+			if (ret==0)
+				regs->pc += rm + 4;
+		}
+		else if ((instruction&0x00FF)==0x0003) {
+			/* bsrf @Rm */
+			ret = handle_unaligned_delayslot(regs);
+			if (ret==0) {
+				regs->pr = regs->pc + 4;
+				regs->pc += rm + 4;
+			}
+		}
+		else {
+			/* mov.[bwl] to/from memory via r0+rn */
+			goto simple;
+		}
+		break;
+
+	case 0x1000: /* mov.l Rm,@(disp,Rn) */
+		goto simple;
+
+	case 0x2000: /* mov.[bwl] to memory, possibly with pre-decrement */
+		goto simple;
+
+	case 0x4000:
+		if ((instruction&0x00FF)==0x002B) {
+			/* jmp @Rm */
+			ret = handle_unaligned_delayslot(regs);
+			if (ret==0)
+				regs->pc = rm;
+		}
+		else if ((instruction&0x00FF)==0x000B) {
+			/* jsr @Rm */
+			ret = handle_unaligned_delayslot(regs);
+			if (ret==0) {
+				regs->pr = regs->pc + 4;
+				regs->pc = rm;
+			}
+		}
+		else {
+			/* mov.[bwl] to/from memory via r0+rn */
+			goto simple;
+		}
+		break;
+
+	case 0x5000: /* mov.l @(disp,Rm),Rn */
+		goto simple;
+
+	case 0x6000: /* mov.[bwl] from memory, possibly with post-increment */
+		goto simple;
+
+	case 0x8000: /* bf lab, bf/s lab, bt lab, bt/s lab */
+		switch (instruction&0x0F00) {
+		case 0x0100: /* mov.w R0,@(disp,Rm) */
+			goto simple;
+		case 0x0500: /* mov.w @(disp,Rm),R0 */
+			goto simple;
+		case 0x0B00: /* bf   lab - no delayslot*/
+			break;
+		case 0x0F00: /* bf/s lab */
+			ret = handle_unaligned_delayslot(regs);
+			if (ret==0)
+				regs->pc += (instruction&0x00FF)*2 + 4;
+			break;
+		case 0x0900: /* bt   lab - no delayslot */
+			break;
+		case 0x0D00: /* bt/s lab */
+			ret = handle_unaligned_delayslot(regs);
+			if (ret==0)
+				regs->pc += (instruction&0x00FF)*2 + 4;
+			break;
+		}
+		break;
+
+	case 0xA000: /* bra label */
+		ret = handle_unaligned_delayslot(regs);
+		if (ret==0)
+			regs->pc += (instruction&0x0FFF)*2 + 4;
+		break;
+
+	case 0xB000: /* bsr label */
+		ret = handle_unaligned_delayslot(regs);
+		if (ret==0) {
+			regs->pr = regs->pc + 4;
+			regs->pc += (instruction&0x0FFF)*2 + 4;
+		}
+		break;
+	}
+	return ret;
+
+	/* handle non-delay-slot instruction */
+ simple:
+	ret = handle_unaligned_ins(instruction,regs);
+	if (ret==0)
+		regs->pc += 2;
+	return ret;
+}
+
+/*
+ * Handle various address error exceptions
+ */
+asmlinkage void do_address_error(struct pt_regs *regs, 
+				 unsigned long writeaccess,
+				 unsigned long address)
+{
+	unsigned long error_code;
+	mm_segment_t oldfs;
+	u16 instruction;
+	int tmp;
+
+	asm volatile("stc       r2_bank,%0": "=r" (error_code));
+
+	oldfs = get_fs();
+
+	if (user_mode(regs)) {
+		sti();
+		current->thread.error_code = error_code;
+		current->thread.trap_no = (writeaccess) ? 8 : 7;
+
+		/* bad PC is not something we can fix */
+		if (regs->pc & 1)
+			goto uspace_segv;
+
+		set_fs(USER_DS);
+		if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
+			/* Argh. Fault on the instruction itself.
+			   This should never happen non-SMP
+			*/
+			set_fs(oldfs);
+			goto uspace_segv;
+		}
+
+		tmp = handle_unaligned_access(instruction, regs);
+		set_fs(oldfs);
+
+		if (tmp==0)
+			return; /* sorted */
+
+	uspace_segv:
+		printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm);
+		force_sig(SIGSEGV, current);
+	} else {
+		if (regs->pc & 1)
+			die("unaligned program counter", regs, error_code);
+
+		set_fs(KERNEL_DS);
+		if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
+			/* Argh. Fault on the instruction itself.
+			   This should never happen non-SMP
+			*/
+			set_fs(oldfs);
+			die("insn faulting in do_address_error", regs, 0);
+		}
+
+		handle_unaligned_access(instruction, regs);
+		set_fs(oldfs);
+	}
 }
 
-DO_ERROR( 7, SIGSEGV, "address error (load)", address_error_load, current)
-DO_ERROR( 8, SIGSEGV, "address error (store)", address_error_store, current)
 DO_ERROR(12, SIGILL,  "reserved instruction", reserved_inst, current)
 DO_ERROR(13, SIGILL,  "illegal slot instruction", illegal_slot_inst, current)
 
@@ -93,25 +497,42 @@
 				   struct pt_regs regs)
 {
 	long ex;
-	asm volatile("stc	$r2_bank, %0" : "=r" (ex));
+	asm volatile("stc	r2_bank, %0" : "=r" (ex));
 	die_if_kernel("exception", &regs, ex);
 }
 
+#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)
+void *gdb_vbr_vector;
+#endif
+
 void __init trap_init(void)
 {
 	extern void *vbr_base;
 	extern void *exception_handling_table[14];
 
-	exception_handling_table[7] = (void *)do_address_error_load;
-	exception_handling_table[8] = (void *)do_address_error_store;
 	exception_handling_table[12] = (void *)do_reserved_inst;
 	exception_handling_table[13] = (void *)do_illegal_slot_inst;
 
+#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS)
+    	/*
+	 * Read the old value of the VBR register to initialise
+	 * the vector through which debug and BIOS traps are
+	 * delegated by the Linux trap handler.
+	 */
+	{
+	    register unsigned long vbr;
+	    asm volatile("stc vbr, %0" : "=r" (vbr));
+	    gdb_vbr_vector = (void *)(vbr + 0x100);
+	    printk("Setting GDB trap vector to 0x%08lx\n",
+	    	(unsigned long)gdb_vbr_vector);
+	}
+#endif
+
 	/* NOTE: The VBR value should be at P1
 	   (or P2, virtural "fixed" address space).
 	   It's definitely should not in physical address.  */
 
-	asm volatile("ldc	%0, $vbr"
+	asm volatile("ldc	%0, vbr"
 		     : /* no output */
 		     : "r" (&vbr_base)
 		     : "memory");
@@ -123,8 +544,8 @@
 	unsigned long *end;
 	unsigned long *p;
 
-	asm("mov	$r15, %0" : "=r" (start));
-	asm("stc	$r7_bank, %0" : "=r" (end));
+	asm("mov	r15, %0" : "=r" (start));
+	asm("stc	r7_bank, %0" : "=r" (end));
 	end += 8192/4;
 
 	printk("%08lx:%08lx\n", (unsigned long)start, (unsigned long)end);
diff -u --recursive --new-file v2.4.0/linux/arch/sh/lib/checksum.S linux/arch/sh/lib/checksum.S
--- v2.4.0/linux/arch/sh/lib/checksum.S	Mon Oct  2 11:57:34 2000
+++ linux/arch/sh/lib/checksum.S	Sun Jan 28 18:56:00 2001
@@ -49,99 +49,99 @@
 	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
 	   * alignment for the unrolled loop.
 	   */
-	mov	$r5, $r1
-	mov	$r4, $r0
-	tst	#2, $r0		! Check alignment.
+	mov	r5, r1
+	mov	r4, r0
+	tst	#2, r0		! Check alignment.
 	bt	2f		! Jump if alignment is ok.
 	!
-	add	#-2, $r5	! Alignment uses up two bytes.
-	cmp/pz	$r5		!
+	add	#-2, r5	! Alignment uses up two bytes.
+	cmp/pz	r5		!
 	bt/s	1f		! Jump if we had at least two bytes.
 	 clrt
 	bra	6f
-	 add	#2, $r5		! $r5 was < 2.  Deal with it.
+	 add	#2, r5		! r5 was < 2.  Deal with it.
 1:
-	mov.w	@$r4+, $r0
-	extu.w	$r0, $r0
-	addc	$r0, $r6
+	mov.w	@r4+, r0
+	extu.w	r0, r0
+	addc	r0, r6
 	bf	2f
-	add	#1, $r6
+	add	#1, r6
 2:
-	mov	#-5, $r0
-	shld	$r0, $r5
-	tst	$r5, $r5
+	mov	#-5, r0
+	shld	r0, r5
+	tst	r5, r5
 	bt/s	4f		! if it's =0, go to 4f
 	 clrt
 	.align	2
 3:
-	mov.l	@$r4+, $r0
-	mov.l	@$r4+, $r2
-	mov.l	@$r4+, $r3
-	addc	$r0, $r6
-	mov.l	@$r4+, $r0
-	addc	$r2, $r6
-	mov.l	@$r4+, $r2
-	addc	$r3, $r6
-	mov.l	@$r4+, $r3
-	addc	$r0, $r6
-	mov.l	@$r4+, $r0
-	addc	$r2, $r6
-	mov.l	@$r4+, $r2
-	addc	$r3, $r6
-	addc	$r0, $r6
-	addc	$r2, $r6
-	movt	$r0	
-	dt	$r5
+	mov.l	@r4+, r0
+	mov.l	@r4+, r2
+	mov.l	@r4+, r3
+	addc	r0, r6
+	mov.l	@r4+, r0
+	addc	r2, r6
+	mov.l	@r4+, r2
+	addc	r3, r6
+	mov.l	@r4+, r3
+	addc	r0, r6
+	mov.l	@r4+, r0
+	addc	r2, r6
+	mov.l	@r4+, r2
+	addc	r3, r6
+	addc	r0, r6
+	addc	r2, r6
+	movt	r0	
+	dt	r5
 	bf/s	3b
-	 cmp/eq	#1, $r0
-	! here, we know $r5==0
-	addc	$r5, $r6		! add carry to $r6
+	 cmp/eq	#1, r0
+	! here, we know r5==0
+	addc	r5, r6			! add carry to r6
 4:
-	mov	$r1, $r0
-	and	#0x1c, $r0
-	tst	$r0, $r0
+	mov	r1, r0
+	and	#0x1c, r0
+	tst	r0, r0
 	bt/s	6f
-	 mov	$r0, $r5
-	shlr2	$r5
-	mov	#0, $r2
+	 mov	r0, r5
+	shlr2	r5
+	mov	#0, r2
 5:
-	addc	$r2, $r6
-	mov.l	@$r4+, $r2
-	movt	$r0
-	dt	$r5
+	addc	r2, r6
+	mov.l	@r4+, r2
+	movt	r0
+	dt	r5
 	bf/s	5b
-	 cmp/eq	#1, $r0
-	addc	$r2, $r6
-	addc	$r5, $r6	! $r5==0 here, so it means add carry-bit
+	 cmp/eq	#1, r0
+	addc	r2, r6
+	addc	r5, r6		! r5==0 here, so it means add carry-bit
 6:
-	mov	$r1, $r5
-	mov	#3, $r0
-	and	$r0, $r5
-	tst	$r5, $r5
+	mov	r1, r5
+	mov	#3, r0
+	and	r0, r5
+	tst	r5, r5
 	bt	9f		! if it's =0 go to 9f
-	mov	#2, $r1
-	cmp/hs  $r1, $r5
+	mov	#2, r1
+	cmp/hs  r1, r5
 	bf	7f
-	mov.w	@r4+, $r0
-	extu.w	$r0, $r0
-	cmp/eq	$r1, $r5
+	mov.w	@r4+, r0
+	extu.w	r0, r0
+	cmp/eq	r1, r5
 	bt/s	8f
 	 clrt
-	shll16	$r0
-	addc	$r0, $r6
+	shll16	r0
+	addc	r0, r6
 7:
-	mov.b	@$r4+, $r0
-	extu.b	$r0, $r0
+	mov.b	@r4+, r0
+	extu.b	r0, r0
 #ifndef	__LITTLE_ENDIAN__
-	shll8	$r0
+	shll8	r0
 #endif
 8:
-	addc	$r0, $r6
-	mov	#0, $r0
-	addc	$r0, $r6 
+	addc	r0, r6
+	mov	#0, r0
+	addc	r0, r6 
 9:
 	rts
-	 mov	$r6, $r0
+	 mov	r6, r0
 
 /*
 unsigned int csum_partial_copy_generic (const char *src, char *dst, int len, 
@@ -159,14 +159,14 @@
  *	  them all but there's no guarantee.
  */
 
-#define SRC(x,y)			\
-	9999: x,y;			\
+#define SRC(...)			\
+	9999: __VA_ARGS__ ;		\
 	.section __ex_table, "a";	\
 	.long 9999b, 6001f	;	\
 	.previous
 
-#define DST(x,y)			\
-	9999: x,y;			\
+#define DST(...)			\
+	9999: __VA_ARGS__ ;		\
 	.section __ex_table, "a";	\
 	.long 9999b, 6002f	;	\
 	.previous
@@ -202,7 +202,7 @@
 	bt/s	1f
 	 clrt
 	bra	4f
-	 add	#2,r6			! $r6 was < 2.	Deal with it.
+	 add	#2,r6			! r6 was < 2.	Deal with it.
 
 3:	! Handle different src and dest alinments.
 	! This is not common, so simple byte by byte copy will do.
@@ -211,7 +211,8 @@
 	tst	r6, r6
 	bt	4f
 	clrt
-SRC(5:	mov.b	@r4+,r0	)
+5:	
+SRC(	mov.b	@r4+,r0 )
 DST(	mov.b	r0,@r5	)
 	add	#1, r5
 SRC(	mov.b	@r4+,r1	)
@@ -244,7 +245,8 @@
 	! src and dest equally aligned, but to a two byte boundary.
 	! Handle first two bytes as a special case
 	.align	5
-SRC(1:	mov.w	@r4+,r0	)
+1:	
+SRC(	mov.w	@r4+,r0	)
 DST(	mov.w	r0,@r5	)
 	add	#2,r5
 	extu.w	r0,r0
@@ -258,7 +260,8 @@
 	tst	r6,r6
 	bt/s	2f
 	 clrt
-SRC(1:	mov.l	@r4+,r0	)
+1:	
+SRC(	mov.l	@r4+,r0	)
 SRC(	mov.l	@r4+,r1	)
 	addc	r0,r7
 DST(	mov.l	r0,@r5	)
@@ -276,7 +279,7 @@
 DST(	mov.l	r1,@r5	)
 	add	#4,r5
 
-SRC(	mov.l	@r4+,r0 )
+SRC(	mov.l	@r4+,r0 	)
 SRC(	mov.l	@r4+,r1	)
 	addc	r0,r7
 DST(	mov.l	r0,@r5	)
@@ -307,7 +310,8 @@
 	bf/s	4f
 	 clrt
 	shlr2	r6
-SRC(3:	mov.l	@r4+,r0	)
+3:	
+SRC(	mov.l	@r4+,r0	)
 	addc	r0,r7
 DST(	mov.l	r0,@r5	)
 	add	#4,r5
@@ -334,7 +338,8 @@
 	 clrt
 	shll16	r0
 	addc	r0,r7
-SRC(5:	mov.b	@r4+,r0	)
+5:	
+SRC(	mov.b	@r4+,r0	)
 DST(	mov.b	r0,@r5	)
 	extu.b	r0,r0
 #ifndef	__LITTLE_ENDIAN__
diff -u --recursive --new-file v2.4.0/linux/arch/sh/lib/delay.c linux/arch/sh/lib/delay.c
--- v2.4.0/linux/arch/sh/lib/delay.c	Thu Jan  4 13:19:13 2001
+++ linux/arch/sh/lib/delay.c	Sun Jan 28 18:56:00 2001
@@ -21,7 +21,11 @@
 
 inline void __const_udelay(unsigned long xloops)
 {
-	xloops *= current_cpu_data.loops_per_jiffy;
+	__asm__("dmulu.l	%0, %2\n\t"
+		"sts	mach, %0"
+		: "=r" (xloops)
+		: "0" (xloops), "r" (current_cpu_data.loops_per_jiffy)
+		: "macl", "mach");
 	__delay(xloops * HZ);
 }
 
diff -u --recursive --new-file v2.4.0/linux/arch/sh/mm/cache.c linux/arch/sh/mm/cache.c
--- v2.4.0/linux/arch/sh/mm/cache.c	Mon Oct  2 11:57:34 2000
+++ linux/arch/sh/mm/cache.c	Sun Jan 28 18:56:00 2001
@@ -244,6 +244,22 @@
 }
 
 /*
+ * Write back the D-cache and purge the I-cache for signal trampoline. 
+ */
+void flush_cache_sigtramp(unsigned long addr)
+{
+	unsigned long v, index;
+
+	v = addr & ~(L1_CACHE_BYTES-1);
+	asm volatile("ocbwb	%0"
+		     : /* no output */
+		     : "m" (__m(v)));
+
+	index = CACHE_IC_ADDRESS_ARRAY| (v&CACHE_IC_ENTRY_MASK);
+	ctrl_outl(0, index);	/* Clear out Valid-bit */
+}
+
+/*
  * Invalidate the I-cache of the page (don't need to write back D-cache).
  *
  * Called from kernel/ptrace.c, mm/memory.c after flush_page_to_ram is called.
diff -u --recursive --new-file v2.4.0/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.4.0/linux/arch/sparc/config.in	Tue Nov 28 21:53:44 2000
+++ linux/arch/sparc/config.in	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.106 2000/11/17 04:27:52 davem Exp $
+# $Id: config.in,v 1.107 2001/01/06 00:46:44 davem Exp $
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
@@ -28,6 +28,9 @@
 define_bool CONFIG_VT_CONSOLE y
 
 bool 'Symmetric multi-processing support (does not work on sun4/sun4c)' CONFIG_SMP
+
+# Identify this as a Sparc32 build
+define_bool CONFIG_SPARC32 y
 
 # Global things across all Sun machines.
 define_bool CONFIG_ISA n
diff -u --recursive --new-file v2.4.0/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.4.0/linux/arch/sparc/defconfig	Thu Aug 10 12:43:12 2000
+++ linux/arch/sparc/defconfig	Mon Jan 22 13:30:20 2001
@@ -22,7 +22,10 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 # CONFIG_SMP is not set
+CONFIG_SPARC32=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
 # CONFIG_PCMCIA is not set
 CONFIG_SBUS=y
 CONFIG_SBUSCHAR=y
@@ -64,6 +67,7 @@
 #
 CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_SBUS=y
 CONFIG_FB_CGSIX=y
 CONFIG_FB_BWTWO=y
@@ -111,10 +115,18 @@
 CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
+
+#
+# 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
+# CONFIG_LVM_PROC_FS is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -132,10 +144,8 @@
 # CONFIG_IP_MULTICAST is not set
 # 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_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 CONFIG_IPV6=m
@@ -148,7 +158,6 @@
 #
 CONFIG_IPX=m
 # CONFIG_IPX_INTERN is not set
-# CONFIG_SPX is not set
 CONFIG_ATALK=m
 CONFIG_DECNET=m
 CONFIG_DECNET_SIOCGIFCONF=y
@@ -157,6 +166,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
@@ -228,6 +238,7 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
+# CONFIG_TUN is not set
 CONFIG_PPP=m
 CONFIG_PPP_ASYNC=m
 CONFIG_PPP_SYNC_TTY=m
@@ -302,6 +313,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
@@ -309,8 +321,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
 
@@ -320,6 +330,7 @@
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
 CONFIG_SUN_PARTITION=y
+CONFIG_SMB_NLS=y
 CONFIG_NLS=y
 
 #
diff -u --recursive --new-file v2.4.0/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v2.4.0/linux/arch/sparc/kernel/entry.S	Mon Jan  1 10:37:41 2001
+++ linux/arch/sparc/kernel/entry.S	Mon Jan 29 08:08:46 2001
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.168 2001/01/01 01:46:15 davem Exp $
+/* $Id: entry.S,v 1.169 2001/01/25 21:47:20 davem Exp $
  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -999,6 +999,7 @@
 
 	ld	[%l4 + 0x18], %l3
 	inc	%l3			! sun4c_kernel_ring.num_entries++
+	st	%l3, [%l4 + 0x18]
 	b	4f
 	 ld	[%l6 + 0x08], %l5
 
diff -u --recursive --new-file v2.4.0/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c
--- v2.4.0/linux/arch/sparc/kernel/pcic.c	Mon Dec 11 12:37:02 2000
+++ linux/arch/sparc/kernel/pcic.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.20 2000/12/05 00:56:36 anton Exp $
+/* $Id: pcic.c,v 1.21 2001/01/18 00:23:00 davem Exp $
  * pcic.c: Sparc/PCI controller support
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
@@ -897,93 +897,6 @@
 	regs->pc = regs->npc;
 	regs->npc += 4;
 }
-
-/*
- * XXX  Gleb wrote me that he needs this for X server (only).
- * Since we successfuly use XF86_FBDev, we do not need these anymore.
- *
- *  Following code added to handle extra PCI-related system calls 
- */
-asmlinkage int sys_pciconfig_read(unsigned long bus,
-				  unsigned long dfn,
-				  unsigned long off,
-				  unsigned long len,
-				  unsigned char *buf)
-{
-	unsigned char ubyte;
-	unsigned short ushort;
-	unsigned int uint;
-	int err = 0;
-
-	if(!suser())
-		return -EPERM;
-
-	switch(len) {
-	case 1:
-		pcibios_read_config_byte(bus, dfn, off, &ubyte);
-		put_user(ubyte, (unsigned char *)buf);
-		break;
-	case 2:
-		pcibios_read_config_word(bus, dfn, off, &ushort);
-		put_user(ushort, (unsigned short *)buf);
-		break;
-	case 4:
-		pcibios_read_config_dword(bus, dfn, off, &uint);
-		put_user(uint, (unsigned int *)buf);
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-	};
-
-	return err;
-}
-
-asmlinkage int sys_pciconfig_write(unsigned long bus,
-				   unsigned long dfn,
-				   unsigned long off,
-				   unsigned long len,
-				   unsigned char *buf)
-{
-	unsigned char ubyte;
-	unsigned short ushort;
-	unsigned int uint;
-	int err = 0;
-
-	if(!suser())
-		return -EPERM;
-
-	switch(len) {
-	case 1:
-		err = get_user(ubyte, (unsigned char *)buf);
-		if(err)
-			break;
-		pcibios_write_config_byte(bus, dfn, off, ubyte);
-		break;
-
-	case 2:
-		err = get_user(ushort, (unsigned short *)buf);
-		if(err)
-			break;
-		pcibios_write_config_byte(bus, dfn, off, ushort);
-		break;
-
-	case 4:
-		err = get_user(uint, (unsigned int *)buf);
-		if(err)
-			break;
-		pcibios_write_config_byte(bus, dfn, off, uint);
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-
-	};
-
-	return err;
-}			   
 
 static inline unsigned long get_irqmask(int irq_nr)
 {
diff -u --recursive --new-file v2.4.0/linux/arch/sparc/kernel/semaphore.c linux/arch/sparc/kernel/semaphore.c
--- v2.4.0/linux/arch/sparc/kernel/semaphore.c	Thu Jan  4 13:00:55 2001
+++ linux/arch/sparc/kernel/semaphore.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: semaphore.c,v 1.5 2000/12/29 10:35:05 anton Exp $ */
+/* $Id: semaphore.c,v 1.6 2001/01/05 04:40:07 davem Exp $ */
 
 /* sparc32 semaphore implementation, based on i386 version */
 
diff -u --recursive --new-file v2.4.0/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v2.4.0/linux/arch/sparc/kernel/signal.c	Thu Sep  7 08:32:00 2000
+++ linux/arch/sparc/kernel/signal.c	Wed Jan 24 15:18:06 2001
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.107 2000/09/05 21:44:54 davem Exp $
+/*  $Id: signal.c,v 1.108 2001/01/24 21:05:12 davem Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -27,9 +27,6 @@
 #include <asm/pgtable.h>
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-			 int options, unsigned long *ru);
 
 extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
 		   void *fpqueue, unsigned long *fpqdepth);
diff -u --recursive --new-file v2.4.0/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.4.0/linux/arch/sparc/kernel/sparc_ksyms.c	Mon Dec 11 12:37:02 2000
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.105 2000/12/11 05:24:25 anton Exp $
+/* $Id: sparc_ksyms.c,v 1.106 2001/01/11 15:07:09 davem Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -154,6 +154,7 @@
 #endif
 
 EXPORT_SYMBOL(udelay);
+EXPORT_SYMBOL(mostek_lock);
 EXPORT_SYMBOL(mstk48t02_regs);
 #if CONFIG_SUN_AUXIO
 EXPORT_SYMBOL(auxio_register);
diff -u --recursive --new-file v2.4.0/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.4.0/linux/arch/sparc/kernel/sys_sunos.c	Sat Aug 12 12:08:49 2000
+++ linux/arch/sparc/kernel/sys_sunos.c	Wed Jan 24 15:18:06 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.130 2000/08/12 13:25:41 davem Exp $
+/* $Id: sys_sunos.c,v 1.131 2001/01/24 21:05:12 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -834,7 +834,6 @@
 }
 
 /* So stupid... */
-extern asmlinkage int sys_wait4(pid_t, unsigned int *, int, struct rusage *);
 asmlinkage int sunos_wait4(pid_t pid, unsigned int *stat_addr, int options, struct rusage *ru)
 {
 	int ret;
diff -u --recursive --new-file v2.4.0/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v2.4.0/linux/arch/sparc/kernel/time.c	Sun Sep 17 10:01:49 2000
+++ linux/arch/sparc/kernel/time.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.57 2000/09/16 07:33:45 davem Exp $
+/* $Id: time.c,v 1.58 2001/01/11 15:07:09 davem Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -44,6 +44,7 @@
 extern rwlock_t xtime_lock;
 
 enum sparc_clock_type sp_clock_typ;
+spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED;
 unsigned long mstk48t02_regs = 0UL;
 static struct mostek48t08 *mstk48t08_regs = 0;
 static int set_rtc_mmss(unsigned long);
@@ -158,12 +159,16 @@
 
 	prom_printf("CLOCK: Clock was stopped. Kick start ");
 
+	spin_lock_irq(&mostek_lock);
+
 	/* Turn on the kick start bit to start the oscillator. */
 	regs->creg |= MSTK_CREG_WRITE;
 	regs->sec &= ~MSTK_STOP;
 	regs->hour |= MSTK_KICK_START;
 	regs->creg &= ~MSTK_CREG_WRITE;
 
+	spin_unlock_irq(&mostek_lock);
+
 	/* Delay to allow the clock oscillator to start. */
 	sec = MSTK_REG_SEC(regs);
 	for (i = 0; i < 3; i++) {
@@ -175,6 +180,8 @@
 	}
 	prom_printf("\n");
 
+	spin_lock_irq(&mostek_lock);
+
 	/* Turn off kick start and set a "valid" time and date. */
 	regs->creg |= MSTK_CREG_WRITE;
 	regs->hour &= ~MSTK_KICK_START;
@@ -187,12 +194,17 @@
 	MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO);
 	regs->creg &= ~MSTK_CREG_WRITE;
 
+	spin_unlock_irq(&mostek_lock);
+
 	/* Ensure the kick start bit is off. If it isn't, turn it off. */
 	while (regs->hour & MSTK_KICK_START) {
 		prom_printf("CLOCK: Kick start still on!\n");
+
+		spin_lock_irq(&mostek_lock);
 		regs->creg |= MSTK_CREG_WRITE;
 		regs->hour &= ~MSTK_KICK_START;
 		regs->creg &= ~MSTK_CREG_WRITE;
+		spin_unlock_irq(&mostek_lock);
 	}
 
 	prom_printf("CLOCK: Kick start procedure successful.\n");
@@ -204,10 +216,12 @@
 	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
 	unsigned char data1, data2;
 
+	spin_lock_irq(&mostek_lock);
 	data1 = regs->eeprom[0];	/* Read some data. */
 	regs->eeprom[0] = ~data1;	/* Write back the complement. */
 	data2 = regs->eeprom[0];	/* Read back the complement. */
 	regs->eeprom[0] = data1;	/* Restore the original value. */
+	spin_unlock_irq(&mostek_lock);
 
 	return (data1 == data2);	/* Was the write blocked? */
 }
@@ -376,6 +390,7 @@
 		prom_printf("Something wrong, clock regs not mapped yet.\n");
 		prom_halt();
 	}		
+	spin_lock_irq(&mostek_lock);
 	mregs->creg |= MSTK_CREG_READ;
 	sec = MSTK_REG_SEC(mregs);
 	min = MSTK_REG_MIN(mregs);
@@ -386,6 +401,7 @@
 	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
 	xtime.tv_usec = 0;
 	mregs->creg &= ~MSTK_CREG_READ;
+	spin_unlock_irq(&mostek_lock);
 #ifdef CONFIG_SUN4
 	} else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) {
 		/* initialise the intersil on sun4 */
@@ -520,6 +536,7 @@
 {
 	int real_seconds, real_minutes, mostek_minutes;
 	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
+	unsigned long flags;
 #ifdef CONFIG_SUN4
 	struct intersil *iregs = intersil_clock;
 	int temp;
@@ -557,6 +574,8 @@
 		}
 #endif
 	}
+
+	spin_lock_irqsave(&mostek_lock, flags);
 	/* Read the current RTC minutes. */
 	regs->creg |= MSTK_CREG_READ;
 	mostek_minutes = MSTK_REG_MIN(regs);
@@ -579,8 +598,10 @@
 		MSTK_SET_REG_SEC(regs,real_seconds);
 		MSTK_SET_REG_MIN(regs,real_minutes);
 		regs->creg &= ~MSTK_CREG_WRITE;
-	} else
+		spin_unlock_irqrestore(&mostek_lock, flags);
+		return 0;
+	} else {
+		spin_unlock_irqrestore(&mostek_lock, flags);
 		return -1;
-
-	return 0;
+	}
 }
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.4.0/linux/arch/sparc64/config.in	Thu Nov 16 12:51:28 2000
+++ linux/arch/sparc64/config.in	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.125 2000/10/10 01:05:53 davem Exp $
+# $Id: config.in,v 1.130 2001/01/18 04:47:44 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -26,6 +26,9 @@
 
 bool 'Symmetric multi-processing support' CONFIG_SMP
 
+# Identify this as a Sparc64 build
+define_bool CONFIG_SPARC64 y
+
 # Global things across all Sun machines.
 define_bool CONFIG_HAVE_DEC_LOCK y
 define_bool CONFIG_ISA n
@@ -70,6 +73,7 @@
 if [ "$CONFIG_PCI" = "y" ]; then
    tristate 'SUNW, envctrl support' CONFIG_ENVCTRL
    tristate '7-Segment Display support' CONFIG_DISPLAY7SEG
+   tristate 'CP1XXX Hardware Watchdog support' CONFIG_WATCHDOG_CP1XXX
 fi
 endmenu
 
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.4.0/linux/arch/sparc64/defconfig	Mon Oct 30 14:34:12 2000
+++ linux/arch/sparc64/defconfig	Mon Jan 29 08:08:46 2001
@@ -20,8 +20,11 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 # CONFIG_SMP is not set
+CONFIG_SPARC64=y
 CONFIG_HAVE_DEC_LOCK=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
 # CONFIG_PCMCIA is not set
 CONFIG_SBUS=y
 CONFIG_SBUSCHAR=y
@@ -66,6 +69,7 @@
 CONFIG_PRINTER=m
 CONFIG_ENVCTRL=m
 CONFIG_DISPLAY7SEG=m
+CONFIG_WATCHDOG_CP1XXX=m
 
 #
 # Console drivers
@@ -122,9 +126,7 @@
 # Linux/SPARC audio subsystem (EXPERIMENTAL)
 #
 CONFIG_SPARCAUDIO=y
-# CONFIG_SPARCAUDIO_AMD7930 is not set
 CONFIG_SPARCAUDIO_CS4231=y
-# CONFIG_SPARCAUDIO_DBRI is not set
 # CONFIG_SPARCAUDIO_DUMMY is not set
 
 #
@@ -180,7 +182,6 @@
 #
 CONFIG_IPX=m
 # CONFIG_IPX_INTERN is not set
-# CONFIG_SPX is not set
 CONFIG_ATALK=m
 CONFIG_DECNET=m
 CONFIG_DECNET_SIOCGIFCONF=y
@@ -415,6 +416,8 @@
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+# 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=m
@@ -470,8 +473,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
 
@@ -481,6 +482,7 @@
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
 CONFIG_SUN_PARTITION=y
+# CONFIG_SMB_NLS is not set
 CONFIG_NLS=y
 
 #
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.4.0/linux/arch/sparc64/kernel/ioctl32.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/sparc64/kernel/ioctl32.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.104 2001/01/03 09:28:19 anton Exp $
+/* $Id: ioctl32.c,v 1.105 2001/01/18 04:47:44 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -73,6 +73,7 @@
 #include <asm/audioio.h>
 #include <linux/ethtool.h>
 #include <asm/display7seg.h>
+#include <asm/watchdog.h>
 #include <asm/module.h>
 #include <linux/soundcard.h>
 
@@ -3600,6 +3601,16 @@
 /* elevator */
 COMPATIBLE_IOCTL(BLKELVGET)
 COMPATIBLE_IOCTL(BLKELVSET)
+/* Big W */
+/* WIOC_GETSUPPORT not yet implemented -E */
+COMPATIBLE_IOCTL(WDIOC_GETSTATUS)
+COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS)
+COMPATIBLE_IOCTL(WDIOC_GETTEMP)
+COMPATIBLE_IOCTL(WDIOC_SETOPTIONS)
+COMPATIBLE_IOCTL(WDIOC_KEEPALIVE)
+COMPATIBLE_IOCTL(WIOCSTART)
+COMPATIBLE_IOCTL(WIOCSTOP)
+COMPATIBLE_IOCTL(WIOCGSTAT)
 /* And these ioctls need translation */
 HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
 HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
--- v2.4.0/linux/arch/sparc64/kernel/pci.c	Fri Dec 29 14:07:21 2000
+++ linux/arch/sparc64/kernel/pci.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.20 2000/12/14 22:57:25 davem Exp $
+/* $Id: pci.c,v 1.21 2001/01/10 18:22:59 davem Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -78,6 +78,9 @@
 /* Probe for all PCI controllers in the system. */
 extern void sabre_init(int);
 extern void psycho_init(int);
+#if 0
+extern void schizo_init(int);
+#endif
 
 static struct {
 	char *model_name;
@@ -87,6 +90,10 @@
 	{ "pci108e,a000", sabre_init },
 	{ "SUNW,psycho", psycho_init },
 	{ "pci108e,8000", psycho_init }
+#if 0
+	{ "SUNW,schizo", schizo_init },
+	{ "pci108e,8001", schizo_init }
+#endif
 };
 #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
 				  sizeof(pci_controller_table[0]))
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/pci_iommu.c linux/arch/sparc64/kernel/pci_iommu.c
--- v2.4.0/linux/arch/sparc64/kernel/pci_iommu.c	Fri Mar 10 09:43:04 2000
+++ linux/arch/sparc64/kernel/pci_iommu.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_iommu.c,v 1.11 2000/03/10 02:42:15 davem Exp $
+/* $Id: pci_iommu.c,v 1.12 2001/01/11 16:26:45 davem Exp $
  * pci_iommu.c: UltraSparc PCI controller IOM/STC support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -187,7 +187,7 @@
 	memset((char *)first_page, 0, PAGE_SIZE << order);
 
 	pcp = pdev->sysdata;
-	iommu = &pcp->pbm->parent->iommu;
+	iommu = pcp->pbm->iommu;
 
 	spin_lock_irqsave(&iommu->lock, flags);
 	iopte = alloc_consistent_cluster(iommu, size >> PAGE_SHIFT);
@@ -241,7 +241,7 @@
 
 	npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
 	pcp = pdev->sysdata;
-	iommu = &pcp->pbm->parent->iommu;
+	iommu = pcp->pbm->iommu;
 	iopte = iommu->page_table +
 		((dvma - iommu->page_table_map_base) >> PAGE_SHIFT);
 
@@ -308,7 +308,7 @@
 	unsigned long iopte_protection;
 
 	pcp = pdev->sysdata;
-	iommu = &pcp->pbm->parent->iommu;
+	iommu = pcp->pbm->iommu;
 	strbuf = &pcp->pbm->stc;
 
 	if (direction == PCI_DMA_NONE)
@@ -356,7 +356,7 @@
 		BUG();
 
 	pcp = pdev->sysdata;
-	iommu = &pcp->pbm->parent->iommu;
+	iommu = pcp->pbm->iommu;
 	strbuf = &pcp->pbm->stc;
 
 	npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK);
@@ -504,7 +504,7 @@
 	}
 
 	pcp = pdev->sysdata;
-	iommu = &pcp->pbm->parent->iommu;
+	iommu = pcp->pbm->iommu;
 	strbuf = &pcp->pbm->stc;
 	
 	if (direction == PCI_DMA_NONE)
@@ -568,7 +568,7 @@
 		BUG();
 
 	pcp = pdev->sysdata;
-	iommu = &pcp->pbm->parent->iommu;
+	iommu = pcp->pbm->iommu;
 	strbuf = &pcp->pbm->stc;
 	
 	bus_addr = sglist->dvma_address & PAGE_MASK;
@@ -639,7 +639,7 @@
 	unsigned long flags, ctx, npages;
 
 	pcp = pdev->sysdata;
-	iommu = &pcp->pbm->parent->iommu;
+	iommu = pcp->pbm->iommu;
 	strbuf = &pcp->pbm->stc;
 
 	if (!strbuf->strbuf_enabled)
@@ -700,7 +700,7 @@
 	unsigned long flags, ctx;
 
 	pcp = pdev->sysdata;
-	iommu = &pcp->pbm->parent->iommu;
+	iommu = pcp->pbm->iommu;
 	strbuf = &pcp->pbm->stc;
 
 	if (!strbuf->strbuf_enabled)
@@ -762,7 +762,7 @@
 	if (pdev == NULL) {
 		dma_addr_mask = 0xffffffff;
 	} else {
-		struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+		struct pci_iommu *iommu = pcp->pbm->iommu;
 
 		dma_addr_mask = iommu->dma_addr_mask;
 	}
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- v2.4.0/linux/arch/sparc64/kernel/pci_psycho.c	Tue Oct  3 09:24:41 2000
+++ linux/arch/sparc64/kernel/pci_psycho.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.17 2000/09/21 06:25:14 anton Exp $
+/* $Id: pci_psycho.c,v 1.18 2001/01/11 16:26:45 davem Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -619,20 +619,21 @@
 				     unsigned long afar,
 				     enum psycho_error_type type)
 {
+	struct pci_iommu *iommu = p->pbm_A.iommu;
 	unsigned long iommu_tag[16];
 	unsigned long iommu_data[16];
 	unsigned long flags;
 	u64 control;
 	int i;
 
-	spin_lock_irqsave(&p->iommu.lock, flags);
-	control = psycho_read(p->iommu.iommu_control);
+	spin_lock_irqsave(&iommu->lock, flags);
+	control = psycho_read(iommu->iommu_control);
 	if (control & PSYCHO_IOMMU_CTRL_XLTEERR) {
 		char *type_string;
 
 		/* Clear the error encountered bit. */
 		control &= ~PSYCHO_IOMMU_CTRL_XLTEERR;
-		psycho_write(p->iommu.iommu_control, control);
+		psycho_write(iommu->iommu_control, control);
 
 		switch((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) {
 		case 0:
@@ -662,7 +663,7 @@
 		 * get as much diagnostic information to the
 		 * console as we can.
 		 */
-		psycho_write(p->iommu.iommu_control,
+		psycho_write(iommu->iommu_control,
 			     control | PSYCHO_IOMMU_CTRL_DENAB);
 		for (i = 0; i < 16; i++) {
 			unsigned long base = p->controller_regs;
@@ -678,7 +679,7 @@
 		}
 
 		/* Leave diagnostic mode. */
-		psycho_write(p->iommu.iommu_control, control);
+		psycho_write(iommu->iommu_control, control);
 
 		for (i = 0; i < 16; i++) {
 			unsigned long tag, data;
@@ -717,7 +718,7 @@
 		}
 	}
 	__psycho_check_stc_error(p, afsr, afar, type);
-	spin_unlock_irqrestore(&p->iommu.lock, flags);
+	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
 /* Uncorrectable Errors.  Cause of the error and the address are
@@ -1255,24 +1256,25 @@
 
 static void __init psycho_iommu_init(struct pci_controller_info *p)
 {
+	struct pci_iommu *iommu = p->pbm_A.iommu;
 	unsigned long tsbbase, i;
 	u64 control;
 
 	/* Setup initial software IOMMU state. */
-	spin_lock_init(&p->iommu.lock);
-	p->iommu.iommu_cur_ctx = 0;
+	spin_lock_init(&iommu->lock);
+	iommu->iommu_cur_ctx = 0;
 
 	/* Register addresses. */
-	p->iommu.iommu_control  = p->controller_regs + PSYCHO_IOMMU_CONTROL;
-	p->iommu.iommu_tsbbase  = p->controller_regs + PSYCHO_IOMMU_TSBBASE;
-	p->iommu.iommu_flush    = p->controller_regs + PSYCHO_IOMMU_FLUSH;
+	iommu->iommu_control  = p->controller_regs + PSYCHO_IOMMU_CONTROL;
+	iommu->iommu_tsbbase  = p->controller_regs + PSYCHO_IOMMU_TSBBASE;
+	iommu->iommu_flush    = p->controller_regs + PSYCHO_IOMMU_FLUSH;
 	/* PSYCHO's IOMMU lacks ctx flushing. */
-	p->iommu.iommu_ctxflush = 0;
+	iommu->iommu_ctxflush = 0;
 
 	/* We use the main control register of PSYCHO as the write
 	 * completion register.
 	 */
-	p->iommu.write_complete_reg = p->controller_regs + PSYCHO_CONTROL;
+	iommu->write_complete_reg = p->controller_regs + PSYCHO_CONTROL;
 
 	/*
 	 * Invalidate TLB Entries.
@@ -1298,19 +1300,19 @@
 		prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n");
 		prom_halt();
 	}
-	p->iommu.page_table = (iopte_t *)tsbbase;
-	p->iommu.page_table_sz_bits = 17;
-	p->iommu.page_table_map_base = 0xc0000000;
-	p->iommu.dma_addr_mask = 0xffffffff;
+	iommu->page_table = (iopte_t *)tsbbase;
+	iommu->page_table_sz_bits = 17;
+	iommu->page_table_map_base = 0xc0000000;
+	iommu->dma_addr_mask = 0xffffffff;
 	memset((char *)tsbbase, 0, PAGE_SIZE << 7);
 
 	/* We start with no consistent mappings. */
-	p->iommu.lowest_consistent_map =
-		1 << (p->iommu.page_table_sz_bits - PBM_LOGCLUSTERS);
+	iommu->lowest_consistent_map =
+		1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS);
 
 	for (i = 0; i < PBM_NCLUSTERS; i++) {
-		p->iommu.alloc_info[i].flush = 0;
-		p->iommu.alloc_info[i].next = 0;
+		iommu->alloc_info[i].flush = 0;
+		iommu->alloc_info[i].next = 0;
 	}
 
 	psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
@@ -1515,6 +1517,7 @@
 {
 	struct linux_prom64_registers pr_regs[3];
 	struct pci_controller_info *p;
+	struct pci_iommu *iommu;
 	unsigned long flags;
 	u32 upa_portid;
 	int is_pbm_a, err;
@@ -1538,6 +1541,13 @@
 		prom_halt();
 	}
 	memset(p, 0, sizeof(*p));
+	iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
+	if (!iommu) {
+		prom_printf("PSYCHO: Fatal memory allocation error.\n");
+		prom_halt();
+	}
+	memset(iommu, 0, sizeof(*iommu));
+	p->pbm_A.iommu = p->pbm_B.iommu = iommu;
 
 	spin_lock_irqsave(&pci_controller_lock, flags);
 	p->next = pci_controller_root;
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.4.0/linux/arch/sparc64/kernel/pci_sabre.c	Wed Jul  5 12:14:54 2000
+++ linux/arch/sparc64/kernel/pci_sabre.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.20 2000/06/26 19:40:27 davem Exp $
+/* $Id: pci_sabre.c,v 1.22 2001/01/16 13:03:48 anton Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -672,14 +672,15 @@
 				    unsigned long afsr,
 				    unsigned long afar)
 {
+	struct pci_iommu *iommu = p->pbm_A.iommu;
 	unsigned long iommu_tag[16];
 	unsigned long iommu_data[16];
 	unsigned long flags;
 	u64 control;
 	int i;
 
-	spin_lock_irqsave(&p->iommu.lock, flags);
-	control = sabre_read(p->iommu.iommu_control);
+	spin_lock_irqsave(&iommu->lock, flags);
+	control = sabre_read(iommu->iommu_control);
 	if (control & SABRE_IOMMUCTRL_ERR) {
 		char *type_string;
 
@@ -687,7 +688,7 @@
 		 * NOTE: On Sabre this is write 1 to clear,
 		 *       which is different from Psycho.
 		 */
-		sabre_write(p->iommu.iommu_control, control);
+		sabre_write(iommu->iommu_control, control);
 		switch((control & SABRE_IOMMUCTRL_ERRSTS) >> 25UL) {
 		case 1:
 			type_string = "Invalid Error";
@@ -706,7 +707,7 @@
 		 * entries in the IOTLB.
 		 */
 		control &= ~(SABRE_IOMMUCTRL_ERRSTS | SABRE_IOMMUCTRL_ERR);
-		sabre_write(p->iommu.iommu_control,
+		sabre_write(iommu->iommu_control,
 			    (control | SABRE_IOMMUCTRL_DENAB));
 		for (i = 0; i < 16; i++) {
 			unsigned long base = p->controller_regs;
@@ -718,7 +719,7 @@
 			sabre_write(base + SABRE_IOMMU_TAG + (i * 8UL), 0);
 			sabre_write(base + SABRE_IOMMU_DATA + (i * 8UL), 0);
 		}
-		sabre_write(p->iommu.iommu_control, control);
+		sabre_write(iommu->iommu_control, control);
 
 		for (i = 0; i < 16; i++) {
 			unsigned long tag, data;
@@ -752,7 +753,7 @@
 			       ((data & SABRE_IOMMUDATA_PPN) << PAGE_SHIFT));
 		}
 	}
-	spin_unlock_irqrestore(&p->iommu.lock, flags);
+	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
 static void sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
@@ -1158,20 +1159,21 @@
 				    int tsbsize, unsigned long dvma_offset,
 				    u32 dma_mask)
 {
+	struct pci_iommu *iommu = p->pbm_A.iommu;
 	unsigned long tsbbase, i, order;
 	u64 control;
 
 	/* Setup initial software IOMMU state. */
-	spin_lock_init(&p->iommu.lock);
-	p->iommu.iommu_cur_ctx = 0;
+	spin_lock_init(&iommu->lock);
+	iommu->iommu_cur_ctx = 0;
 
 	/* Register addresses. */
-	p->iommu.iommu_control  = p->controller_regs + SABRE_IOMMU_CONTROL;
-	p->iommu.iommu_tsbbase  = p->controller_regs + SABRE_IOMMU_TSBBASE;
-	p->iommu.iommu_flush    = p->controller_regs + SABRE_IOMMU_FLUSH;
-	p->iommu.write_complete_reg = p->controller_regs + SABRE_WRSYNC;
+	iommu->iommu_control  = p->controller_regs + SABRE_IOMMU_CONTROL;
+	iommu->iommu_tsbbase  = p->controller_regs + SABRE_IOMMU_TSBBASE;
+	iommu->iommu_flush    = p->controller_regs + SABRE_IOMMU_FLUSH;
+	iommu->write_complete_reg = p->controller_regs + SABRE_WRSYNC;
 	/* Sabre's IOMMU lacks ctx flushing. */
-	p->iommu.iommu_ctxflush = 0;
+	iommu->iommu_ctxflush = 0;
                                         
 	/* Invalidate TLB Entries. */
 	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
@@ -1192,9 +1194,9 @@
 		prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
 		prom_halt();
 	}
-	p->iommu.page_table = (iopte_t *)tsbbase;
-	p->iommu.page_table_map_base = dvma_offset;
-	p->iommu.dma_addr_mask = dma_mask;
+	iommu->page_table = (iopte_t *)tsbbase;
+	iommu->page_table_map_base = dvma_offset;
+	iommu->dma_addr_mask = dma_mask;
 	memset((char *)tsbbase, 0, PAGE_SIZE << order);
 
 	sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
@@ -1205,11 +1207,11 @@
 	switch(tsbsize) {
 	case 64:
 		control |= SABRE_IOMMU_TSBSZ_64K;
-		p->iommu.page_table_sz_bits = 16;
+		iommu->page_table_sz_bits = 16;
 		break;
 	case 128:
 		control |= SABRE_IOMMU_TSBSZ_128K;
-		p->iommu.page_table_sz_bits = 17;
+		iommu->page_table_sz_bits = 17;
 		break;
 	default:
 		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
@@ -1219,12 +1221,12 @@
 	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
 
 	/* We start with no consistent mappings. */
-	p->iommu.lowest_consistent_map =
-		1 << (p->iommu.page_table_sz_bits - PBM_LOGCLUSTERS);
+	iommu->lowest_consistent_map =
+		1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS);
 
 	for (i = 0; i < PBM_NCLUSTERS; i++) {
-		p->iommu.alloc_info[i].flush = 0;
-		p->iommu.alloc_info[i].next = 0;
+		iommu->alloc_info[i].flush = 0;
+		iommu->alloc_info[i].next = 0;
 	}
 }
 
@@ -1368,6 +1370,7 @@
 {
 	struct linux_prom64_registers pr_regs[2];
 	struct pci_controller_info *p;
+	struct pci_iommu *iommu;
 	unsigned long flags;
 	int tsbsize, err;
 	u32 busrange[2];
@@ -1380,10 +1383,17 @@
 		prom_printf("SABRE: Error, kmalloc(pci_controller_info) failed.\n");
 		prom_halt();
 	}
+	memset(p, 0, sizeof(*p));
 
-	upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
+	iommu = kmalloc(sizeof(*iommu), GFP_ATOMIC);
+	if (!iommu) {
+		prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n");
+		prom_halt();
+	}
+	memset(iommu, 0, sizeof(*iommu));
+	p->pbm_A.iommu = p->pbm_B.iommu = iommu;
 
-	memset(p, 0, sizeof(*p));
+	upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
 
 	spin_lock_irqsave(&pci_controller_lock, flags);
 	p->next = pci_controller_root;
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/pci_schizo.c linux/arch/sparc64/kernel/pci_schizo.c
--- v2.4.0/linux/arch/sparc64/kernel/pci_schizo.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/pci_schizo.c	Mon Jan 22 13:30:20 2001
@@ -0,0 +1,169 @@
+/* $Id: pci_schizo.c,v 1.2 2001/01/12 02:43:30 davem Exp $
+ * pci_schizo.c: SCHIZO specific PCI controller support.
+ *
+ * Copyright (C) 2001 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+
+#include <asm/pbm.h>
+#include <asm/iommu.h>
+#include <asm/irq.h>
+
+#include "pci_impl.h"
+
+static int schizo_read_byte(struct pci_dev *dev, int where, u8 *value)
+{
+	/* IMPLEMENT ME */
+}
+
+static int schizo_read_word(struct pci_dev *dev, int where, u16 *value)
+{
+	/* IMPLEMENT ME */
+}
+
+static int schizo_read_dword(struct pci_dev *dev, int where, u32 *value)
+{
+	/* IMPLEMENT ME */
+}
+
+static int schizo_write_byte(struct pci_dev *dev, int where, u8 value)
+{
+	/* IMPLEMENT ME */
+}
+
+static int schizo_write_word(struct pci_dev *dev, int where, u16 value)
+{
+	/* IMPLEMENT ME */
+}
+
+static int schizo_write_dword(struct pci_dev *dev, int where, u32 value)
+{
+	/* IMPLEMENT ME */
+}
+
+static struct pci_ops schizo_ops = {
+	schizo_read_byte,
+	schizo_read_word,
+	schizo_read_dword,
+	schizo_write_byte,
+	schizo_write_word,
+	schizo_write_dword
+};
+
+static void __init schizo_scan_bus(struct pci_controller_info *p)
+{
+	/* IMPLEMENT ME */
+}
+
+static unsigned int __init schizo_irq_build(struct pci_controller_info *p,
+					    struct pci_dev *pdev,
+					    unsigned int ino)
+{
+	/* IMPLEMENT ME */
+}
+
+static void __init schizo_base_address_update(struct pci_dev *pdev, int resource)
+{
+	/* IMPLEMENT ME */
+}
+
+static void __init schizo_resource_adjust(struct pci_dev *pdev,
+					  struct resource *res,
+					  struct resource *root)
+{
+	/* IMPLEMENT ME */
+}
+
+static void schizo_pbm_init(struct pci_controller_info *p,
+			    int prom_node, int is_pbm_a)
+{
+	/* IMPLEMENT ME */
+}
+
+void __init schizo_init(int node)
+{
+	struct linux_prom64_registers pr_regs[3];
+	struct pci_controller_info *p;
+	struct pci_iommu *iommu;
+	u32 portid;
+	int is_pbm_a, err;
+
+	portid = prom_getintdefault(node, "portid", 0xff);
+
+	spin_lock_irqsave(&pci_controller_lock, flags);
+	for(p = pci_controller_root; p; p = p->next) {
+		if (p->portid == portid) {
+			spin_unlock_irqrestore(&pci_controller_lock, flags);
+			is_pbm_a = (p->pbm_A.prom_node == 0);
+			schizo_pbm_init(p, node, is_pbm_a);
+			return;
+		}
+	}
+	spin_unlock_irqrestore(&pci_controller_lock, flags);
+
+	p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
+	if (!p) {
+		prom_printf("SCHIZO: Fatal memory allocation error.\n");
+		prom_halt();
+	}
+	memset(p, 0, sizeof(*p));
+
+	iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
+	if (!iommu) {
+		prom_printf("SCHIZO: Fatal memory allocation error.\n");
+		prom_halt();
+	}
+	memset(iommu, 0, sizeof(*iommu));
+	p->pbm_A.iommu = iommu;
+
+	iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
+	if (!iommu) {
+		prom_printf("SCHIZO: Fatal memory allocation error.\n");
+		prom_halt();
+	}
+	memset(iommu, 0, sizeof(*iommu));
+	p->pbm_B.iommu = iommu;
+
+	spin_lock_irqsave(&pci_controller_lock, flags);
+	p->next = pci_controller_root;
+	pci_controller_root = p;
+	spin_unlock_irqrestore(&pci_controller_lock, flags);
+
+	p->portid = portid;
+	p->index = pci_num_controllers++;
+	p->scan_bus = schizo_scan_bus;
+	p->irq_build = schizo_irq_build;
+	p->base_address_update = schizo_base_address_update;
+	p->resource_adjust = schizo_resource_adjust;
+	p->pci_ops = &schizo_ops;
+
+pbm_init:
+	/* Three OBP regs:
+	 * 1) PBM controller regs
+	 * 2) Schizo front-end controller regs (same for both PBMs)
+	 * 3) Unknown... (0x7ffec000000 and 0x7ffee000000 on Excalibur)
+	 */
+	err = prom_getproperty(node, "reg",
+			       (char *)&pr_regs[0],
+			       sizeof(pr_regs));
+	if (err == 0 || err == -1) {
+		prom_printf("SCHIZO: Fatal error, no reg property.\n");
+		prom_halt();
+	}
+
+	/* XXX Read REG base, record in controller/pbm structures. */
+
+	/* XXX Report controller to console. */
+
+	/* XXX Setup pci_memspace_mask */
+
+	/* XXX Init core controller and IOMMU */
+
+	is_pbm_a = XXX; /* Figure out this test */
+	schizo_pbm_init(p, node, is_pbm_a);
+}
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c
--- v2.4.0/linux/arch/sparc64/kernel/signal.c	Thu Sep  7 08:32:00 2000
+++ linux/arch/sparc64/kernel/signal.c	Wed Jan 24 15:18:06 2001
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.54 2000/09/05 21:44:54 davem Exp $
+/*  $Id: signal.c,v 1.55 2001/01/24 21:05:13 davem Exp $
  *  arch/sparc64/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -30,9 +30,6 @@
 #include <asm/visasm.h>
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-			 int options, unsigned long *ru);
 
 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
 			 unsigned long orig_o0, int ret_from_syscall);
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c
--- v2.4.0/linux/arch/sparc64/kernel/signal32.c	Thu Sep  7 08:32:00 2000
+++ linux/arch/sparc64/kernel/signal32.c	Wed Jan 24 15:18:06 2001
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.67 2000/09/05 21:44:54 davem Exp $
+/*  $Id: signal32.c,v 1.68 2001/01/24 21:05:13 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -28,9 +28,6 @@
 #include <asm/visasm.h>
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-			 int options, unsigned long *ru);
 
 asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs,
 			 unsigned long orig_o0, int ret_from_syscall);
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.4.0/linux/arch/sparc64/kernel/smp.c	Mon Jan  1 10:37:41 2001
+++ linux/arch/sparc64/kernel/smp.c	Mon Jan 29 08:08:46 2001
@@ -290,8 +290,8 @@
 		}
 		printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
 		       cpucount + 1,
-		       (bogosum + 2500)/500000,
-		       ((bogosum + 2500)/5000)%100);
+		       bogosum/(500000/HZ),
+		       (bogosum/(5000/HZ))%100);
 		smp_activated = 1;
 		smp_num_cpus = cpucount + 1;
 	}
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.4.0/linux/arch/sparc64/kernel/sparc64_ksyms.c	Mon Dec 11 12:37:03 2000
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.99 2000/12/09 04:15:24 anton Exp $
+/* $Id: sparc64_ksyms.c,v 1.100 2001/01/11 15:07:09 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -182,6 +182,7 @@
 EXPORT_SYMBOL(flush_icache_range);
 EXPORT_SYMBOL(__flush_dcache_page);
 
+EXPORT_SYMBOL(mostek_lock);
 EXPORT_SYMBOL(mstk48t02_regs);
 EXPORT_SYMBOL(request_fast_irq);
 #if CONFIG_SBUS
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.4.0/linux/arch/sparc64/kernel/sys_sparc32.c	Fri Dec 29 14:07:21 2000
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Wed Jan 24 15:18:06 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.171 2000/12/13 16:34:55 davem Exp $
+/* $Id: sys_sparc32.c,v 1.172 2001/01/24 21:05:13 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -1793,9 +1793,6 @@
 	err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
 	return err;
 }
-
-extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr,
-				int options, struct rusage * ru);
 
 asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
 {
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.4.0/linux/arch/sparc64/kernel/sys_sunos32.c	Tue Nov 28 21:53:44 2000
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.55 2000/11/18 02:10:59 davem Exp $
+/* $Id: sys_sunos32.c,v 1.56 2001/01/04 05:35:48 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -1047,6 +1047,7 @@
 			(current->thread.kregs->u_regs[UREG_FP] & 0xffffffffUL);
 		if(get_user(arg5, &sp->xxargs[0])) {
 			rval = -EFAULT;
+			kfree(kmbuf);
 			break;
 		}
 		set_fs(KERNEL_DS);
diff -u --recursive --new-file v2.4.0/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- v2.4.0/linux/arch/sparc64/kernel/time.c	Tue Oct  3 09:24:41 2000
+++ linux/arch/sparc64/kernel/time.c	Mon Jan 22 13:30:20 2001
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.32 2000/09/22 23:02:13 davem Exp $
+/* $Id: time.c,v 1.33 2001/01/11 15:07:09 davem Exp $
  * time.c: UltraSparc timer and TOD clock support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -34,7 +34,9 @@
 
 extern rwlock_t xtime_lock;
 
+spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED;
 unsigned long mstk48t02_regs = 0UL;
+
 static unsigned long mstk48t08_regs = 0UL;
 static unsigned long mstk48t59_regs = 0UL;
 
@@ -187,6 +189,8 @@
 
 	prom_printf("CLOCK: Clock was stopped. Kick start ");
 
+	spin_lock_irq(&mostek_lock);
+
 	/* Turn on the kick start bit to start the oscillator. */
 	tmp = mostek_read(regs + MOSTEK_CREG);
 	tmp |= MSTK_CREG_WRITE;
@@ -201,6 +205,8 @@
 	tmp &= ~MSTK_CREG_WRITE;
 	mostek_write(regs + MOSTEK_CREG, tmp);
 
+	spin_unlock_irq(&mostek_lock);
+
 	/* Delay to allow the clock oscillator to start. */
 	sec = MSTK_REG_SEC(regs);
 	for (i = 0; i < 3; i++) {
@@ -212,6 +218,8 @@
 	}
 	prom_printf("\n");
 
+	spin_lock_irq(&mostek_lock);
+
 	/* Turn off kick start and set a "valid" time and date. */
 	tmp = mostek_read(regs + MOSTEK_CREG);
 	tmp |= MSTK_CREG_WRITE;
@@ -230,9 +238,14 @@
 	tmp &= ~MSTK_CREG_WRITE;
 	mostek_write(regs + MOSTEK_CREG, tmp);
 
+	spin_unlock_irq(&mostek_lock);
+
 	/* Ensure the kick start bit is off. If it isn't, turn it off. */
 	while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) {
 		prom_printf("CLOCK: Kick start still on!\n");
+
+		spin_lock_irq(&mostek_lock);
+
 		tmp = mostek_read(regs + MOSTEK_CREG);
 		tmp |= MSTK_CREG_WRITE;
 		mostek_write(regs + MOSTEK_CREG, tmp);
@@ -244,6 +257,8 @@
 		tmp = mostek_read(regs + MOSTEK_CREG);
 		tmp &= ~MSTK_CREG_WRITE;
 		mostek_write(regs + MOSTEK_CREG, tmp);
+
+		spin_unlock_irq(&mostek_lock);
 	}
 
 	prom_printf("CLOCK: Kick start procedure successful.\n");
@@ -255,11 +270,15 @@
 	unsigned long regs = mstk48t02_regs;
 	u8 data1, data2;
 
+	spin_lock_irq(&mostek_lock);
+
 	data1 = mostek_read(regs + MOSTEK_EEPROM);	/* Read some data. */
 	mostek_write(regs + MOSTEK_EEPROM, ~data1);	/* Write back the complement. */
 	data2 = mostek_read(regs + MOSTEK_EEPROM);	/* Read back the complement. */
 	mostek_write(regs + MOSTEK_EEPROM, data1);	/* Restore original value. */
 
+	spin_unlock_irq(&mostek_lock);
+
 	return (data1 == data2);	/* Was the write blocked? */
 }
 
@@ -278,6 +297,8 @@
 		prom_halt();
 	}		
 
+	spin_lock_irq(&mostek_lock);
+
 	tmp = mostek_read(mregs + MOSTEK_CREG);
 	tmp |= MSTK_CREG_READ;
 	mostek_write(mregs + MOSTEK_CREG, tmp);
@@ -294,6 +315,8 @@
 	tmp = mostek_read(mregs + MOSTEK_CREG);
 	tmp &= ~MSTK_CREG_READ;
 	mostek_write(mregs + MOSTEK_CREG, tmp);
+
+	spin_unlock_irq(&mostek_lock);
 }
 
 void __init clock_probe(void)
@@ -512,6 +535,7 @@
 {
 	int real_seconds, real_minutes, mostek_minutes;
 	unsigned long regs = mstk48t02_regs;
+	unsigned long flags;
 	u8 tmp;
 
 	/* 
@@ -521,6 +545,8 @@
 	if (!regs) 
 		return -1;
 
+	spin_lock_irqsave(&mostek_lock, flags);
+
 	/* Read the current RTC minutes. */
 	tmp = mostek_read(regs + MOSTEK_CREG);
 	tmp |= MSTK_CREG_READ;
@@ -555,8 +581,13 @@
 		tmp = mostek_read(regs + MOSTEK_CREG);
 		tmp &= ~MSTK_CREG_WRITE;
 		mostek_write(regs + MOSTEK_CREG, tmp);
-	} else
-		return -1;
 
-	return 0;
+		spin_unlock_irqrestore(&mostek_lock, flags);
+
+		return 0;
+	} else {
+		spin_unlock_irqrestore(&mostek_lock, flags);
+
+		return -1;
+	}
 }
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/Makefile linux/drivers/acpi/Makefile
--- v2.4.0/linux/drivers/acpi/Makefile	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/Makefile	Mon Jan 22 13:23:42 2001
@@ -4,7 +4,7 @@
 
 O_TARGET := acpi.o
 
-export-objs := ksyms.o
+export-objs := acpi_ksyms.o
 
 export ACPI_CFLAGS
 ACPI_CFLAGS := -D_LINUX
@@ -20,18 +20,26 @@
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
 
+# genksyms only reads $(CFLAGS), it should really read $(EXTRA_CFLAGS) as well.
+# Without EXTRA_CFLAGS the gcc pass for genksyms fails, resulting in an empty
+# include/linux/modules/acpi_ksyms.ver.  Changing genkyms to use EXTRA_CFLAGS
+# will hit everything, too risky in 2.4.0-prerelease.  Bandaid by tweaking
+# CFLAGS only for .ver targets.  Review after 2.4.0 release.  KAO
+
+$(MODINCL)/%.ver: CFLAGS := -I./include $(CFLAGS)
+
 acpi-subdirs := common dispatcher events hardware \
 		interpreter namespace parser resources tables
 
 subdir-$(CONFIG_ACPI) += $(acpi-subdirs)
 
 obj-$(CONFIG_ACPI) := $(patsubst %,%.o,$(acpi-subdirs))
-obj-$(CONFIG_ACPI) += os.o ksyms.o
+obj-$(CONFIG_ACPI) += os.o acpi_ksyms.o
 
 ifdef CONFIG_ACPI_KERNEL_CONFIG
   obj-$(CONFIG_ACPI) += acpiconf.o osconf.o
 else
-  obj-$(CONFIG_ACPI) += driver.o cmbatt.o cpu.o ec.o ksyms.o sys.o table.o power.o
+  obj-$(CONFIG_ACPI) += driver.o cmbatt.o cpu.o ec.o acpi_ksyms.o sys.o table.o power.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/acpi_ksyms.c linux/drivers/acpi/acpi_ksyms.c
--- v2.4.0/linux/drivers/acpi/acpi_ksyms.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/acpi_ksyms.c	Mon Jan 29 10:15:58 2001
@@ -0,0 +1,83 @@
+/*
+ *  ksyms.c - ACPI exported symbols
+ *
+ *  Copyright (C) 2000 Andrew Grover
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/acpi.h>
+#include "acpi.h"
+#include "acdebug.h"
+
+extern int acpi_in_debugger;
+
+#define _COMPONENT	OS_DEPENDENT
+	MODULE_NAME	("symbols")
+
+#ifdef ENABLE_DEBUGGER
+EXPORT_SYMBOL(acpi_in_debugger);
+EXPORT_SYMBOL(acpi_db_user_commands);
+#endif
+
+EXPORT_SYMBOL(acpi_os_free);
+EXPORT_SYMBOL(acpi_os_breakpoint);
+EXPORT_SYMBOL(acpi_os_printf);
+EXPORT_SYMBOL(acpi_os_callocate);
+EXPORT_SYMBOL(acpi_os_sleep);
+EXPORT_SYMBOL(acpi_os_sleep_usec);
+EXPORT_SYMBOL(acpi_os_in8);
+EXPORT_SYMBOL(acpi_os_out8);
+EXPORT_SYMBOL(acpi_os_queue_for_execution);
+
+EXPORT_SYMBOL(acpi_dbg_layer);
+EXPORT_SYMBOL(acpi_dbg_level);
+EXPORT_SYMBOL(function_exit);
+EXPORT_SYMBOL(function_trace);
+EXPORT_SYMBOL(function_status_exit);
+EXPORT_SYMBOL(function_value_exit);
+EXPORT_SYMBOL(debug_print_raw);
+EXPORT_SYMBOL(debug_print_prefix);
+
+EXPORT_SYMBOL(acpi_cm_strncmp);
+EXPORT_SYMBOL(acpi_cm_memcpy);
+EXPORT_SYMBOL(acpi_cm_memset);
+
+EXPORT_SYMBOL(acpi_get_handle);
+EXPORT_SYMBOL(acpi_get_parent);
+EXPORT_SYMBOL(acpi_get_type);
+EXPORT_SYMBOL(acpi_get_name);
+EXPORT_SYMBOL(acpi_get_object_info);
+EXPORT_SYMBOL(acpi_get_next_object);
+EXPORT_SYMBOL(acpi_evaluate_object);
+
+EXPORT_SYMBOL(acpi_install_notify_handler);
+EXPORT_SYMBOL(acpi_remove_notify_handler);
+EXPORT_SYMBOL(acpi_install_gpe_handler);
+EXPORT_SYMBOL(acpi_remove_gpe_handler);
+EXPORT_SYMBOL(acpi_install_address_space_handler);
+EXPORT_SYMBOL(acpi_remove_address_space_handler);
+
+EXPORT_SYMBOL(acpi_get_current_resources);
+EXPORT_SYMBOL(acpi_get_possible_resources);
+EXPORT_SYMBOL(acpi_set_current_resources);
+
+EXPORT_SYMBOL(acpi_enable_event);
+EXPORT_SYMBOL(acpi_disable_event);
+EXPORT_SYMBOL(acpi_clear_event);
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/cmbatt.c linux/drivers/acpi/cmbatt.c
--- v2.4.0/linux/drivers/acpi/cmbatt.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/cmbatt.c	Mon Jan 22 13:23:42 2001
@@ -113,10 +113,10 @@
 	obj = (ACPI_OBJECT *) buf.pointer;
 	objs = obj->package.elements;
 
-	result->state = objs[0].number.value;
-	result->present_rate = objs[1].number.value;
-	result->remaining_capacity = objs[2].number.value;
-	result->present_voltage = objs[3].number.value;
+	result->state = objs[0].integer.value;
+	result->present_rate = objs[1].integer.value;
+	result->remaining_capacity = objs[2].integer.value;
+	result->present_voltage = objs[3].integer.value;
 
 	kfree(buf.pointer);
 
@@ -153,15 +153,15 @@
 	obj = (ACPI_OBJECT *) buf.pointer;
 	objs = obj->package.elements;
 	
-	result->power_unit=objs[0].number.value;
-	result->design_capacity=objs[1].number.value;
-	result->last_full_capacity=objs[2].number.value;
-	result->battery_technology=objs[3].number.value;
-	result->design_voltage=objs[4].number.value;
-	result->design_capacity_warning=objs[5].number.value;
-	result->design_capacity_low=objs[6].number.value;
-	result->battery_capacity_granularity_1=objs[7].number.value;
-	result->battery_capacity_granularity_2=objs[8].number.value;
+	result->power_unit=objs[0].integer.value;
+	result->design_capacity=objs[1].integer.value;
+	result->last_full_capacity=objs[2].integer.value;
+	result->battery_technology=objs[3].integer.value;
+	result->design_voltage=objs[4].integer.value;
+	result->design_capacity_warning=objs[5].integer.value;
+	result->design_capacity_low=objs[6].integer.value;
+	result->battery_capacity_granularity_1=objs[7].integer.value;
+	result->battery_capacity_granularity_2=objs[8].integer.value;
 
 	/* BUG: trailing NULL issue */
 	strncpy(result->model_number, objs[9].string.pointer, MAX_BATT_STRLEN-1);
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmalloc.c linux/drivers/acpi/common/cmalloc.c
--- v2.4.0/linux/drivers/acpi/common/cmalloc.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmalloc.c	Mon Jan 29 10:15:58 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: cmalloc - local memory allocation routines
- *              $Revision: 79 $
+ *              $Revision: 84 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -57,8 +57,6 @@
 	u32                     line)
 {
 	void                    *address = NULL;
-	DEBUG_ONLY_MEMBERS (\
-	ACPI_STATUS             status)
 
 
 	/* Check for an inadvertent size of zero bytes */
@@ -107,8 +105,6 @@
 	u32                     line)
 {
 	void                    *address = NULL;
-	DEBUG_ONLY_MEMBERS (\
-	ACPI_STATUS             status)
 
 
 	/* Check for an inadvertent size of zero bytes */
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmclib.c linux/drivers/acpi/common/cmclib.c
--- v2.4.0/linux/drivers/acpi/common/cmclib.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmclib.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: cmclib - Local implementation of C library functions
- * $Revision: 28 $
+ * $Revision: 32 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -347,7 +347,7 @@
 void *
 acpi_cm_memset (
 	void                    *dest,
-	u32                     value,
+	NATIVE_UINT             value,
 	NATIVE_UINT             count)
 {
 	NATIVE_CHAR             *new = (NATIVE_CHAR *) dest;
@@ -522,6 +522,7 @@
 #define IS_LOWER(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO))
 #define IS_DIGIT(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI))
 #define IS_SPACE(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP))
+#define IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD))
 
 
 /*******************************************************************************
@@ -658,7 +659,7 @@
 acpi_cm_strtoul (
 	const NATIVE_CHAR       *string,
 	NATIVE_CHAR             **terminator,
-	u32                     base)
+	NATIVE_UINT             base)
 {
 	u32                     converted = 0;
 	u32                     index;
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmcopy.c linux/drivers/acpi/common/cmcopy.c
--- v2.4.0/linux/drivers/acpi/common/cmcopy.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmcopy.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: cmcopy - Internal to external object translation utilities
- *              $Revision: 61 $
+ *              $Revision: 62 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -118,9 +118,9 @@
 		break;
 
 
-	case ACPI_TYPE_NUMBER:
+	case ACPI_TYPE_INTEGER:
 
-		external_obj->number.value= internal_obj->number.value;
+		external_obj->integer.value= internal_obj->integer.value;
 		break;
 
 
@@ -469,11 +469,11 @@
 		break;
 
 
-	case ACPI_TYPE_NUMBER:
+	case ACPI_TYPE_INTEGER:
 		/*
 		 * Number is included in the object itself
 		 */
-		internal_obj->number.value  = external_obj->number.value;
+		internal_obj->integer.value  = external_obj->integer.value;
 		break;
 
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmdebug.c linux/drivers/acpi/common/cmdebug.c
--- v2.4.0/linux/drivers/acpi/common/cmdebug.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmdebug.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: cmdebug - Debug print routines
- *              $Revision: 61 $
+ *              $Revision: 64 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -281,7 +281,7 @@
 	u32                     line_number,
 	u32                     component_id,
 	NATIVE_CHAR             *function_name,
-	NATIVE_UINT             value)
+	ACPI_INTEGER            value)
 {
 
 	debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS,
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmdelete.c linux/drivers/acpi/common/cmdelete.c
--- v2.4.0/linux/drivers/acpi/common/cmdelete.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmdelete.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: cmdelete - object deletion and reference count utilities
- *              $Revision: 60 $
+ *              $Revision: 62 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmeval.c linux/drivers/acpi/common/cmeval.c
--- v2.4.0/linux/drivers/acpi/common/cmeval.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmeval.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: cmeval - Object evaluation
- *              $Revision: 19 $
+ *              $Revision: 21 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -77,7 +77,7 @@
 
 	/* Is the return object of the correct type? */
 
-	if (obj_desc->common.type != ACPI_TYPE_NUMBER) {
+	if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
 		status = AE_TYPE;
 	}
 	else {
@@ -85,7 +85,7 @@
 		 * Since the structure is a union, setting any field will set all
 		 * of the variables in the union
 		 */
-		*address = obj_desc->number.value;
+		*address = obj_desc->integer.value;
 	}
 
 	/* On exit, we must delete the return object */
@@ -142,17 +142,17 @@
 	 *  a string
 	 */
 
-	if ((obj_desc->common.type != ACPI_TYPE_NUMBER) &&
+	if ((obj_desc->common.type != ACPI_TYPE_INTEGER) &&
 		(obj_desc->common.type != ACPI_TYPE_STRING))
 	{
 		status = AE_TYPE;
 	}
 
 	else {
-		if (obj_desc->common.type == ACPI_TYPE_NUMBER) {
+		if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
 			/* Convert the Numeric HID to string */
 
-			acpi_aml_eisa_id_to_string ((u32) obj_desc->number.value, hid->buffer);
+			acpi_aml_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer);
 		}
 
 		else {
@@ -217,17 +217,17 @@
 	 *  a string
 	 */
 
-	if ((obj_desc->common.type != ACPI_TYPE_NUMBER) &&
+	if ((obj_desc->common.type != ACPI_TYPE_INTEGER) &&
 		(obj_desc->common.type != ACPI_TYPE_STRING))
 	{
 		status = AE_TYPE;
 	}
 
 	else {
-		if (obj_desc->common.type == ACPI_TYPE_NUMBER) {
+		if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
 			/* Convert the Numeric UID to string */
 
-			acpi_aml_unsigned_integer_to_string (obj_desc->number.value, uid->buffer);
+			acpi_aml_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer);
 		}
 
 		else {
@@ -289,14 +289,14 @@
 
 		/* Is the return object of the correct type? */
 
-		if (obj_desc->common.type != ACPI_TYPE_NUMBER) {
+		if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
 			status = AE_TYPE;
 		}
 
 		else {
 			/* Extract the status flags */
 
-			*flags = (u32) obj_desc->number.value;
+			*flags = (u32) obj_desc->integer.value;
 		}
 
 		/* On exit, we must delete the return object */
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmglobal.c linux/drivers/acpi/common/cmglobal.c
--- v2.4.0/linux/drivers/acpi/common/cmglobal.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmglobal.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: cmglobal - Global variables for the ACPI subsystem
- *              $Revision: 112 $
+ *              $Revision: 116 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -95,7 +95,7 @@
 	{"_SB_",    INTERNAL_TYPE_DEF_ANY},
 	{"_SI_",    INTERNAL_TYPE_DEF_ANY},
 	{"_TZ_",    INTERNAL_TYPE_DEF_ANY},
-	{"_REV",    ACPI_TYPE_NUMBER, "2"},
+	{"_REV",    ACPI_TYPE_INTEGER, "2"},
 	{"_OS_",    ACPI_TYPE_STRING, ACPI_OS_NAME},
 	{"_GL_",    ACPI_TYPE_MUTEX, "0"},
 
@@ -150,6 +150,13 @@
 	NSP_NORMAL,                 /* 33 Extra            */
 	NSP_NORMAL                  /* 34 Invalid          */
 };
+
+
+/* Hex to ASCII conversion table */
+
+NATIVE_CHAR                 acpi_gbl_hex_to_ascii[] =
+			  {'0','1','2','3','4','5','6','7',
+			  '8','9','A','B','C','D','E','F'};
 
 
 /******************************************************************************
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cminit.c linux/drivers/acpi/common/cminit.c
--- v2.4.0/linux/drivers/acpi/common/cminit.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cminit.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: cminit - Common ACPI subsystem initialization
- *              $Revision: 91 $
+ *              $Revision: 93 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -35,6 +35,9 @@
 	 MODULE_NAME         ("cminit")
 
 
+#define ACPI_OFFSET(d,o)    ((u32) &(((d *)0)->o))
+#define ACPI_FADT_OFFSET(o) ACPI_OFFSET (FADT_DESCRIPTOR, o)
+
 /*******************************************************************************
  *
  * FUNCTION:    Acpi_cm_fadt_register_error
@@ -53,12 +56,13 @@
 static ACPI_STATUS
 acpi_cm_fadt_register_error (
 	NATIVE_CHAR             *register_name,
-	u32                     value)
+	u32                     value,
+	u32                     offset)
 {
 
 	REPORT_ERROR (
-		("Invalid FADT register value, %s=%X (FADT=%p)\n",
-		register_name, value, acpi_gbl_FADT));
+		("Invalid FADT value %s=%lX at offset %lX FADT=%p\n",
+		register_name, value, offset, acpi_gbl_FADT));
 
 
 	return (AE_BAD_VALUE);
@@ -91,39 +95,42 @@
 
 	if (acpi_gbl_FADT->pm1_evt_len < 4) {
 		status = acpi_cm_fadt_register_error ("PM1_EVT_LEN",
-				  (u32) acpi_gbl_FADT->pm1_evt_len);
+				  (u32) acpi_gbl_FADT->pm1_evt_len,
+				  ACPI_FADT_OFFSET (pm1_evt_len));
 	}
 
 	if (!acpi_gbl_FADT->pm1_cnt_len) {
-		status = acpi_cm_fadt_register_error ("PM1_CNT_LEN",
-				  0);
+		status = acpi_cm_fadt_register_error ("PM1_CNT_LEN", 0,
+				  ACPI_FADT_OFFSET (pm1_cnt_len));
 	}
 
 	if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)) {
-		status = acpi_cm_fadt_register_error ("PM1a_EVT_BLK",
-				  0);
+		status = acpi_cm_fadt_register_error ("X_PM1a_EVT_BLK", 0,
+				  ACPI_FADT_OFFSET (Xpm1a_evt_blk.address));
 	}
 
 	if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_cnt_blk.address)) {
-		status = acpi_cm_fadt_register_error ("PM1a_CNT_BLK",
-				  0);
+		status = acpi_cm_fadt_register_error ("X_PM1a_CNT_BLK", 0,
+				  ACPI_FADT_OFFSET (Xpm1a_cnt_blk.address));
 	}
 
 	if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)) {
-		status = acpi_cm_fadt_register_error ("PM_TMR_BLK",
-				  0);
+		status = acpi_cm_fadt_register_error ("X_PM_TMR_BLK", 0,
+				  ACPI_FADT_OFFSET (Xpm_tmr_blk.address));
 	}
 
 	if ((ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address) &&
 		!acpi_gbl_FADT->pm2_cnt_len))
 	{
 		status = acpi_cm_fadt_register_error ("PM2_CNT_LEN",
-				  (u32) acpi_gbl_FADT->pm2_cnt_len);
+				  (u32) acpi_gbl_FADT->pm2_cnt_len,
+				  ACPI_FADT_OFFSET (pm2_cnt_len));
 	}
 
 	if (acpi_gbl_FADT->pm_tm_len < 4) {
 		status = acpi_cm_fadt_register_error ("PM_TM_LEN",
-				  (u32) acpi_gbl_FADT->pm_tm_len);
+				  (u32) acpi_gbl_FADT->pm_tm_len,
+				  ACPI_FADT_OFFSET (pm_tm_len));
 	}
 
 	/* length of GPE blocks must be a multiple of 2 */
@@ -132,15 +139,17 @@
 	if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) &&
 		(acpi_gbl_FADT->gpe0blk_len & 1))
 	{
-		status = acpi_cm_fadt_register_error ("GPE0_BLK_LEN",
-				  (u32) acpi_gbl_FADT->gpe0blk_len);
+		status = acpi_cm_fadt_register_error ("(x)GPE0_BLK_LEN",
+				  (u32) acpi_gbl_FADT->gpe0blk_len,
+				  ACPI_FADT_OFFSET (gpe0blk_len));
 	}
 
 	if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) &&
 		(acpi_gbl_FADT->gpe1_blk_len & 1))
 	{
-		status = acpi_cm_fadt_register_error ("GPE1_BLK_LEN",
-				  (u32) acpi_gbl_FADT->gpe1_blk_len);
+		status = acpi_cm_fadt_register_error ("(x)GPE1_BLK_LEN",
+				  (u32) acpi_gbl_FADT->gpe1_blk_len,
+				  ACPI_FADT_OFFSET (gpe1_blk_len));
 	}
 
 	return (status);
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmobject.c linux/drivers/acpi/common/cmobject.c
--- v2.4.0/linux/drivers/acpi/common/cmobject.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmobject.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: cmobject - ACPI object create/delete/size/cache routines
- *              $Revision: 34 $
+ *              $Revision: 35 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -434,7 +434,7 @@
 		break;
 
 
-	case ACPI_TYPE_NUMBER:
+	case ACPI_TYPE_INTEGER:
 	case ACPI_TYPE_PROCESSOR:
 	case ACPI_TYPE_POWER:
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmutils.c linux/drivers/acpi/common/cmutils.c
--- v2.4.0/linux/drivers/acpi/common/cmutils.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmutils.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: cmutils - common utility procedures
- *              $Revision: 21 $
+ *              $Revision: 23 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -647,16 +647,16 @@
 
 		if (sub_object->common.type == INTERNAL_TYPE_REFERENCE) {
 			if (sub_object->reference.op_code == AML_ZERO_OP) {
-				sub_object->common.type = ACPI_TYPE_NUMBER;
-				sub_object->number.value = 0;
+				sub_object->common.type = ACPI_TYPE_INTEGER;
+				sub_object->integer.value = 0;
 			}
 			else if (sub_object->reference.op_code == AML_ONE_OP) {
-				sub_object->common.type = ACPI_TYPE_NUMBER;
-				sub_object->number.value = 1;
+				sub_object->common.type = ACPI_TYPE_INTEGER;
+				sub_object->integer.value = 1;
 			}
 			else if (sub_object->reference.op_code == AML_ONES_OP) {
-				sub_object->common.type = ACPI_TYPE_NUMBER;
-				sub_object->number.value = ACPI_INTEGER_MAX;
+				sub_object->common.type = ACPI_TYPE_INTEGER;
+				sub_object->integer.value = ACPI_INTEGER_MAX;
 			}
 		}
 	}
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/common/cmxface.c linux/drivers/acpi/common/cmxface.c
--- v2.4.0/linux/drivers/acpi/common/cmxface.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/cmxface.c	Mon Jan 29 10:15:58 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: cmxface - External interfaces for "global" ACPI functions
- *              $Revision: 55 $
+ *              $Revision: 62 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -304,16 +304,22 @@
 	out_buffer->length = sizeof (ACPI_SYSTEM_INFO);
 	info_ptr = (ACPI_SYSTEM_INFO *) out_buffer->pointer;
 
-	/* TBD [Future]: need a version number, or use the version string */
-	info_ptr->acpi_ca_version   = 0x1234;
+	info_ptr->acpi_ca_version   = ACPI_CA_VERSION;
 
 	/* System flags (ACPI capabilities) */
 
 	info_ptr->flags             = acpi_gbl_system_flags;
 
 	/* Timer resolution - 24 or 32 bits  */
-
-	info_ptr->timer_resolution  = acpi_hw_pmt_resolution ();
+	if (!acpi_gbl_FADT) {
+		info_ptr->timer_resolution = 0;
+	}
+	else if (acpi_gbl_FADT->tmr_val_ext == 0) {
+		info_ptr->timer_resolution = 24;
+	}
+	else {
+		info_ptr->timer_resolution = 32;
+	}
 
 	/* Clear the reserved fields */
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/cpu.c linux/drivers/acpi/cpu.c
--- v2.4.0/linux/drivers/acpi/cpu.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/cpu.c	Mon Jan 29 10:15:58 2001
@@ -39,6 +39,9 @@
 static int acpi_max_c_state = 1;
 static int acpi_pm_tmr_len;
 
+#define MAX_C2_LATENCY		100
+#define MAX_C3_LATENCY		1000
+
 /*
  * Clear busmaster activity flag
  */
@@ -251,10 +254,7 @@
 acpi_found_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
 {
 	ACPI_OBJECT obj;
-	ACPI_CX_STATE lat[4];
-	ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE];
 	ACPI_BUFFER buf;
-	int i, count;
 
 	buf.length = sizeof(obj);
 	buf.pointer = &obj;
@@ -273,41 +273,28 @@
 
 	acpi_pblk = obj.processor.pblk_address;
 
-	buf.length = sizeof(lat);
-	buf.pointer = lat;
-	if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf)))
-		return AE_OK;
+	if (acpi_fadt.plvl2_lat
+	    && acpi_fadt.plvl2_lat <= MAX_C2_LATENCY) {
+		acpi_c2_exit_latency
+			= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat);
+		acpi_c2_enter_latency
+			= ACPI_MICROSEC_TO_TMR_TICKS(ACPI_TMR_HZ / 1000);
+		acpi_max_c_state = 2;
 
-	if (lat[2].latency < MAX_CX_STATE_LATENCY) {
 		printk(KERN_INFO "ACPI: System firmware supports: C2");
-		acpi_c2_exit_latency = lat[2].latency;
-		acpi_max_c_state = 2;
 	
-		if (lat[3].latency < MAX_CX_STATE_LATENCY) {
-			printk(" C3");
-			acpi_c3_exit_latency = lat[3].latency;
+		if (acpi_fadt.plvl3_lat
+		    && acpi_fadt.plvl3_lat <= MAX_C3_LATENCY) {
+			acpi_c3_exit_latency
+				= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat);
+			acpi_c3_enter_latency
+				= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 5);
 			acpi_max_c_state = 3;
-		}
-		printk("\n");
-	}
 
-	memset(throttle, 0, sizeof(throttle));
-	buf.length = sizeof(throttle);
-	buf.pointer = throttle;
-
-	if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf)))
-		return AE_OK;
-
-	for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) {
-		if (throttle[i].percent_of_clock)
-			count++;
-	}
-
-	/* 0% throttled really doesn't count */
-	count--;
+			printk(" C3");
+		}
 
-	if (count > 0) {
-		DEBUG_PRINT(ACPI_INFO, ("%d throttling states\n", count));
+		printk("\n");
 	}
 
 	return AE_OK;
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dsfield.c linux/drivers/acpi/dispatcher/dsfield.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dsfield.c	Fri Sep 15 14:30:29 2000
+++ linux/drivers/acpi/dispatcher/dsfield.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: dsfield - Dispatcher field routines
- *              $Revision: 29 $
+ *              $Revision: 31 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dsmethod.c linux/drivers/acpi/dispatcher/dsmethod.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dsmethod.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/dispatcher/dsmethod.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
- *              $Revision: 53 $
+ *              $Revision: 56 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dsmthdat.c linux/drivers/acpi/dispatcher/dsmthdat.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dsmthdat.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/dispatcher/dsmthdat.c	Mon Jan 29 10:15:58 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: dsmthdat - control method arguments and local variables
- *              $Revision: 36 $
+ *              $Revision: 39 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -40,7 +40,7 @@
  *
  * FUNCTION:    Acpi_ds_method_data_init
  *
- * PARAMETERS:  *Obj_desc
+ * PARAMETERS:  Walk_state          - Current walk state object
  *
  * RETURN:      Status
  *
@@ -97,7 +97,7 @@
  *
  * FUNCTION:    Acpi_ds_method_data_delete_all
  *
- * PARAMETERS:  None
+ * PARAMETERS:  Walk_state          - Current walk state object
  *
  * RETURN:      Status
  *
@@ -153,7 +153,9 @@
  *
  * FUNCTION:    Acpi_ds_method_data_init_args
  *
- * PARAMETERS:  None
+ * PARAMETERS:  *Params         - Pointer to a parameter list for the method
+ *              Max_param_count - The arg count for this method
+ *              Walk_state      - Current walk state object
  *
  * RETURN:      Status
  *
@@ -214,6 +216,7 @@
  *              Index               - Which local_var or argument to get
  *              Entry               - Pointer to where a pointer to the stack
  *                                    entry is returned.
+ *              Walk_state          - Current walk state object
  *
  * RETURN:      Status
  *
@@ -276,6 +279,7 @@
  * PARAMETERS:  Type                - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
  *              Index               - Which local_var or argument to get
  *              Object              - Object to be inserted into the stack entry
+ *              Walk_state          - Current walk state object
  *
  * RETURN:      Status
  *
@@ -320,6 +324,7 @@
  * PARAMETERS:  Type                - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
  *              Index               - Which local_var or argument whose type
  *                                      to get
+ *              Walk_state          - Current walk state object
  *
  * RETURN:      Data type of selected Arg or Local
  *              Used only in Exec_monadic2()/Type_op.
@@ -366,6 +371,7 @@
  * PARAMETERS:  Type                - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
  *              Index               - Which local_var or argument whose type
  *                                      to get
+ *              Walk_state          - Current walk state object
  *
  * RETURN:      Get the Node associated with a local or arg.
  *
@@ -418,7 +424,8 @@
  *
  * PARAMETERS:  Type                - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
  *              Index               - Which local_var or argument to get
- *              *Dest_desc           - Descriptor into which selected Arg
+ *              Walk_state          - Current walk state object
+ *              *Dest_desc          - Ptr to Descriptor into which selected Arg
  *                                    or Local value should be copied
  *
  * RETURN:      Status
@@ -474,10 +481,12 @@
 		switch (type)
 		{
 		case MTH_TYPE_ARG:
+
 			return (AE_AML_UNINITIALIZED_ARG);
 			break;
 
 		case MTH_TYPE_LOCAL:
+
 			return (AE_AML_UNINITIALIZED_LOCAL);
 			break;
 		}
@@ -502,6 +511,7 @@
  *
  * PARAMETERS:  Type                - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
  *              Index               - Which local_var or argument to delete
+ *              Walk_state          - Current walk state object
  *
  * RETURN:      Status
  *
@@ -548,7 +558,6 @@
 		 * Decrement the reference count by one to balance the
 		 * increment when the object was stored in the slot.
 		 */
-
 		acpi_cm_remove_reference (object);
 	}
 
@@ -563,18 +572,14 @@
  *
  * PARAMETERS:  Type                - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG
  *              Index               - Which local_var or argument to set
- *              *Src_desc           - Value to be stored
- *              *Dest_desc          - Descriptor into which *Src_desc
- *                                    can be copied, or NULL if one must
- *                                    be allocated for the purpose.  If
- *                                    provided, this descriptor will be
- *                                    used for the new value.
+ *              Src_desc            - Value to be stored
+ *              Walk_state          - Current walk state
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Store a value in an Arg or Local.  The Src_desc is installed
  *              as the new value for the Arg or Local and the reference count
- *              is incremented.
+ *              for Src_desc is incremented.
  *
  ******************************************************************************/
 
@@ -644,7 +649,6 @@
 			 * Store this object into the Node
 			 * (do the indirect store)
 			 */
-
 			status = acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) *entry, src_desc,
 					   src_desc->common.type);
 			return (status);
@@ -652,10 +656,18 @@
 
 
 		/*
-		 * Otherwise, just delete the existing object
-		 * before storing the new one
+		 * Perform "Implicit conversion" of the new object to the type of the
+		 * existing object
 		 */
+		status = acpi_aml_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state);
+		if (ACPI_FAILURE (status)) {
+			goto cleanup;
+		}
 
+		/*
+		 * Delete the existing object
+		 * before storing the new one
+		 */
 		acpi_ds_method_data_delete_value (type, index, walk_state);
 	}
 
@@ -666,7 +678,6 @@
 	 * Install the new object in the stack entry
 	 * (increments the object reference count by one)
 	 */
-
 	status = acpi_ds_method_data_set_entry (type, index, src_desc, walk_state);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup;
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dsobject.c linux/drivers/acpi/dispatcher/dsobject.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dsobject.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/dispatcher/dsobject.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: dsobject - Dispatcher object management routines
- *              $Revision: 53 $
+ *              $Revision: 56 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -241,14 +241,14 @@
 
 		/* We are expecting a number */
 
-		if (arg_desc->common.type != ACPI_TYPE_NUMBER) {
+		if (arg_desc->common.type != ACPI_TYPE_INTEGER) {
 			acpi_cm_remove_reference (arg_desc);
 			return (AE_TYPE);
 		}
 
 		/* Get the value, delete the internal object */
 
-		(*obj_desc)->buffer.length = (u32) arg_desc->number.value;
+		(*obj_desc)->buffer.length = (u32) arg_desc->integer.value;
 		acpi_cm_remove_reference (arg_desc);
 
 		/* Allocate the buffer */
@@ -304,8 +304,8 @@
 		status = acpi_ds_build_internal_object (walk_state, op, obj_desc);
 		break;
 
-	case ACPI_TYPE_NUMBER:
-		(*obj_desc)->number.value = op->value.integer;
+	case ACPI_TYPE_INTEGER:
+		(*obj_desc)->integer.value = op->value.integer;
 		break;
 
 
@@ -411,18 +411,20 @@
 					acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, &length, &name);
 
 					if (name) {
-						REPORT_WARNING (("Reference %s AML %X not found\n",
+						REPORT_WARNING (("Reference %s at AML %X not found\n",
 								 name, op->aml_offset));
 						acpi_cm_free (name);
 					}
 					else {
-						REPORT_WARNING (("Reference %s AML %X not found\n",
+						REPORT_WARNING (("Reference %s at AML %X not found\n",
 								   op->value.string, op->aml_offset));
 					}
 					*obj_desc_ptr = NULL;
 				}
 
-				return (status);
+				else {
+					return (status);
+				}
 			}
 		}
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dsopcode.c linux/drivers/acpi/dispatcher/dsopcode.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dsopcode.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/dispatcher/dsopcode.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: dsopcode - Dispatcher Op Region support and handling of
  *                         "control" opcodes
- *              $Revision: 28 $
+ *              $Revision: 30 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -355,7 +355,7 @@
 	}
 
 
-	offset = (u32) off_desc->number.value;
+	offset = (u32) off_desc->integer.value;
 
 
 	/*
@@ -427,7 +427,7 @@
 		/* Offset is in bits, count is in bits */
 
 		bit_offset = offset;
-		bit_count = (u16) cnt_desc->number.value;
+		bit_count = (u16) cnt_desc->integer.value;
 		break;
 
 
@@ -586,7 +586,7 @@
 	 */
 	operand_desc = walk_state->operands[walk_state->num_operands - 1];
 
-	obj_desc->region.length = (u32) operand_desc->number.value;
+	obj_desc->region.length = (u32) operand_desc->integer.value;
 	acpi_cm_remove_reference (operand_desc);
 
 	/*
@@ -595,7 +595,7 @@
 	 */
 	operand_desc = walk_state->operands[walk_state->num_operands - 2];
 
-	obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) operand_desc->number.value;
+	obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) operand_desc->integer.value;
 	acpi_cm_remove_reference (operand_desc);
 
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dsutils.c linux/drivers/acpi/dispatcher/dsutils.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dsutils.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/dispatcher/dsutils.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: dsutils - Dispatcher utilities
- *              $Revision: 50 $
+ *              $Revision: 52 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -566,7 +566,7 @@
 		case AML_WORD_OP:
 		case AML_DWORD_OP:
 
-			data_type = ACPI_TYPE_NUMBER;
+			data_type = ACPI_TYPE_INTEGER;
 			break;
 
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dswexec.c linux/drivers/acpi/dispatcher/dswexec.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dswexec.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/dispatcher/dswexec.c	Mon Jan 29 10:15:58 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: dswexec - Dispatcher method execution callbacks;
  *                        dispatch to interpreter.
- *              $Revision: 50 $
+ *              $Revision: 55 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -46,7 +46,7 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Get the result of a predicate evaluation
  *
  ****************************************************************************/
 
@@ -93,22 +93,22 @@
 	 * be a number
 	 */
 
-	if (obj_desc->common.type != ACPI_TYPE_NUMBER) {
+	if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
 		status = AE_AML_OPERAND_TYPE;
 		goto cleanup;
 	}
 
 
-	/* TBD: 64/32-bit */
+	/* Truncate the predicate to 32-bits if necessary */
 
-	obj_desc->number.value &= (UINT64) 0x00000000FFFFFFFF;
+	acpi_aml_truncate_for32bit_table (obj_desc, walk_state);
 
 	/*
 	 * Save the result of the predicate evaluation on
 	 * the control stack
 	 */
 
-	if (obj_desc->number.value) {
+	if (obj_desc->integer.value) {
 		walk_state->control_state->common.value = TRUE;
 	}
 
@@ -330,6 +330,8 @@
 
 	walk_state->num_operands = 0;
 	walk_state->return_desc = NULL;
+	walk_state->op_info = op_info;
+	walk_state->opcode = opcode;
 
 
 	/* Call debugger for single step support (DEBUG build only) */
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dswload.c linux/drivers/acpi/dispatcher/dswload.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dswload.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/dispatcher/dswload.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: dswload - Dispatcher namespace load callbacks
- *              $Revision: 24 $
+ *              $Revision: 26 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dswscope.c linux/drivers/acpi/dispatcher/dswscope.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dswscope.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/dispatcher/dswscope.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: dswscope - Scope stack manipulation
- *              $Revision: 40 $
+ *              $Revision: 42 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/dispatcher/dswstate.c linux/drivers/acpi/dispatcher/dswstate.c
--- v2.4.0/linux/drivers/acpi/dispatcher/dswstate.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/dispatcher/dswstate.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: dswstate - Dispatcher parse tree walk management routines
- *              $Revision: 36 $
+ *              $Revision: 38 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -37,31 +37,6 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_ds_result_stack_clear
- *
- * PARAMETERS:  Walk_state          - Current Walk state
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Reset this walk's result stack pointers to zero, thus setting
- *              the stack to zero.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-xxx_acpi_ds_result_stack_clear (
-	ACPI_WALK_STATE         *walk_state)
-{
-/*
-	Walk_state->Num_results = 0;
-	Walk_state->Current_result = 0;
-*/
-	return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
  * FUNCTION:    Acpi_ds_result_insert
  *
  * PARAMETERS:  Object              - Object to push
@@ -135,7 +110,7 @@
 	/* Check for a valid result object */
 
 	if (!state->results.obj_desc [index]) {
-		return (AE_AML_NO_OPERAND);
+		return (AE_AML_NO_RETURN_VALUE);
 	}
 
 	/* Remove the object */
@@ -179,7 +154,7 @@
 
 
 	if (!state->results.num_results) {
-		return (AE_STACK_UNDERFLOW);
+		return (AE_AML_NO_RETURN_VALUE);
 	}
 
 	/* Remove top element */
@@ -198,12 +173,12 @@
 	}
 
 
-	return (AE_STACK_UNDERFLOW);
+	return (AE_AML_NO_RETURN_VALUE);
 }
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_ds_result_pop
+ * FUNCTION:    Acpi_ds_result_pop_from_bottom
  *
  * PARAMETERS:  Object              - Where to return the popped object
  *              Walk_state          - Current Walk state
@@ -231,7 +206,7 @@
 
 
 	if (!state->results.num_results) {
-		return (AE_STACK_UNDERFLOW);
+		return (AE_AML_NO_RETURN_VALUE);
 	}
 
 	/* Remove Bottom element */
@@ -250,7 +225,7 @@
 	/* Check for a valid result object */
 
 	if (!*object) {
-		return (AE_AML_NO_OPERAND);
+		return (AE_AML_NO_RETURN_VALUE);
 	}
 
 
@@ -260,15 +235,14 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_ds_result_pop
+ * FUNCTION:    Acpi_ds_result_push
  *
  * PARAMETERS:  Object              - Where to return the popped object
  *              Walk_state          - Current Walk state
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Pop an object off the bottom of this walk's result stack.  In
- *              other words, this is a FIFO.
+ * DESCRIPTION: Push an object onto the current result stack
  *
  ******************************************************************************/
 
@@ -282,7 +256,7 @@
 
 	state = walk_state->results;
 	if (!state) {
-		return (AE_OK);
+		return (AE_AML_INTERNAL);
 	}
 
 	if (state->results.num_results == OBJ_NUM_OPERANDS) {
@@ -719,6 +693,7 @@
 	ACPI_WALK_LIST          *walk_list)
 {
 	ACPI_WALK_STATE         *walk_state;
+	ACPI_STATUS             status;
 
 
 	acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
@@ -736,7 +711,7 @@
 		acpi_gbl_walk_state_cache_depth--;
 
 		acpi_cm_release_mutex (ACPI_MTX_CACHES);
-   }
+	}
 
 	else {
 		/* The cache is empty, create a new object */
@@ -761,6 +736,14 @@
 #ifndef _ACPI_ASL_COMPILER
 	acpi_ds_method_data_init (walk_state);
 #endif
+
+	/* Create an initial result stack entry */
+
+	status = acpi_ds_result_stack_push (walk_state);
+	if (ACPI_FAILURE (status)) {
+		return (NULL);
+	}
+
 
 	/* Put the new state at the head of the walk list */
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/driver.c linux/drivers/acpi/driver.c
--- v2.4.0/linux/drivers/acpi/driver.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/driver.c	Mon Jan 29 10:15:58 2001
@@ -55,7 +55,7 @@
 
 static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED;
 static volatile u32 acpi_event_status = 0;
-static volatile acpi_sstate_t acpi_event_state = ACPI_S0;
+static volatile acpi_sstate_t acpi_event_state = ACPI_STATE_S0;
 static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
 
 static volatile int acpi_thread_pid = -1;
@@ -243,7 +243,7 @@
 /*
  * Enter system sleep state
  */
-static int 
+/*static int 
 acpi_do_sleep(ctl_table * ctl,
 	      int write,
 	      struct file *file,
@@ -257,13 +257,13 @@
 		}
 	}
 	else {
-		int status = acpi_enter_sx(ACPI_S1);
+		int status = acpi_enter_sx(ACPI_STATE_S1);
 		if (status)
 			return status;
 	}
 	file->f_pos += *len;
 	return 0;
-}
+}*/
 
 
 /*
@@ -382,7 +382,8 @@
 	 &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency),
 	 0644, NULL, &acpi_do_ulong},
 
-	{ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},
+/* until it actually works */
+/*	{ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},*/
 
 	{ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
 
@@ -415,7 +416,9 @@
 static int
 acpi_thread(void *context)
 {
-	ACPI_PHYSICAL_ADDRESS rsdp_phys;
+	ACPI_PHYSICAL_ADDRESS	rsdp_phys;
+	ACPI_BUFFER		buffer;
+	ACPI_SYSTEM_INFO	sys_info;
 
 	/*
 	 * initialize
@@ -437,8 +440,6 @@
 	rsdp_phys = efi.acpi;
 #endif
 		
-	printk(KERN_ERR "ACPI: System description tables found\n");
-	
 	if (!ACPI_SUCCESS(acpi_find_and_load_tables(rsdp_phys)))
 		return -ENODEV;
 
@@ -447,6 +448,17 @@
 		acpi_terminate();
 		return -ENODEV;
 	}
+
+	buffer.length  = sizeof(sys_info);
+	buffer.pointer = &sys_info;
+
+	if (!ACPI_SUCCESS (acpi_get_system_info(&buffer))) {
+		printk(KERN_ERR "ACPI: Could not get system info\n");
+		acpi_terminate();
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "ACPI: Core Subsystem version [%x]\n", sys_info.acpi_ca_version);
 
 	if (!ACPI_SUCCESS(acpi_enable_subsystem(ACPI_FULL_INITIALIZATION))) {
 		printk(KERN_ERR "ACPI: Subsystem enable failed\n");
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/ec.c linux/drivers/acpi/ec.c
--- v2.4.0/linux/drivers/acpi/ec.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/ec.c	Mon Jan 29 10:15:58 2001
@@ -270,25 +270,6 @@
     return_ACPI_STATUS(status);
 }
 
-static ACPI_STATUS 
-ec_space_setup (
-    ACPI_HANDLE                 region_handle,
-    UINT32                      function,
-    void                        *handler_context,
-    void                        **return_context)
-{
-	// TODO: What is this function for?
-	/* 
-	 * The ec object is in the handler context and is needed
-	 * when calling the ec_space_handler.
-	 */
-	*return_context = handler_context;
-
-    return AE_OK;
-}
-
-
-
 
 static void
 ec_query_handler (
@@ -419,8 +400,6 @@
 {
 	FUNCTION_TRACE("acpi_ec_region_setup");
 
-	printk("acpi_ec_region_setup\n");
-
 	if (function == ACPI_REGION_DEACTIVATE)
 	{
 		if (*region_context)
@@ -556,10 +535,10 @@
 	buf.length = sizeof(obj);
 	buf.pointer = &obj;
 	if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_GPE", NULL, &buf))
-		|| obj.type != ACPI_TYPE_NUMBER)
+		|| obj.type != ACPI_TYPE_INTEGER)
 		return AE_OK;
 
-	ec_cxt->gpe_bit = obj.number.value;
+	ec_cxt->gpe_bit = obj.integer.value;
 
 	/* determine if we need the Global Lock when accessing */
 	buf.length = sizeof(obj);
@@ -568,12 +547,12 @@
 	status = acpi_evaluate_object(handle, "_GLK", NULL, &buf);
 	if (status == AE_NOT_FOUND)
 		ec_cxt->need_global_lock = 0;
-	else if (!ACPI_SUCCESS(status) || obj.type != ACPI_TYPE_NUMBER) {
+	else if (!ACPI_SUCCESS(status) || obj.type != ACPI_TYPE_INTEGER) {
 		DEBUG_PRINT(ACPI_ERROR, ("_GLK failed\n"));
 		return AE_OK;
 	}
 
-	ec_cxt->need_global_lock = obj.number.value;
+	ec_cxt->need_global_lock = obj.integer.value;
 
 	printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,gpe %d GL %d)\n",
 		ec_cxt->data_port, ec_cxt->status_port, ec_cxt->gpe_bit,
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/events/evevent.c linux/drivers/acpi/events/evevent.c
--- v2.4.0/linux/drivers/acpi/events/evevent.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/events/evevent.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: evevent - Fixed and General Purpose Acpi_event
  *                          handling and dispatch
- *              $Revision: 32 $
+ *              $Revision: 33 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/events/evmisc.c linux/drivers/acpi/events/evmisc.c
--- v2.4.0/linux/drivers/acpi/events/evmisc.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/events/evmisc.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: evmisc - ACPI device notification handler dispatch
  *                       and ACPI Global Lock support
- *              $Revision: 20 $
+ *              $Revision: 22 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/events/evregion.c linux/drivers/acpi/events/evregion.c
--- v2.4.0/linux/drivers/acpi/events/evregion.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/events/evregion.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: evregion - ACPI Address_space (Op_region) handler dispatch
- *              $Revision: 93 $
+ *              $Revision: 94 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -122,8 +122,8 @@
 	u32                     function)
 {
 	ACPI_OPERAND_OBJECT    *params[3];
-	ACPI_OPERAND_OBJECT     space_iD_obj;
-	ACPI_OPERAND_OBJECT     function_obj;
+	ACPI_OPERAND_OBJECT     space_id_desc;
+	ACPI_OPERAND_OBJECT     function_desc;
 	ACPI_STATUS             status;
 
 
@@ -141,24 +141,24 @@
 	 *          Passed as a parameter
 	 */
 
-	acpi_cm_init_static_object (&space_iD_obj);
-	acpi_cm_init_static_object (&function_obj);
+	acpi_cm_init_static_object (&space_id_desc);
+	acpi_cm_init_static_object (&function_desc);
 
 	/*
 	 *  Method requires two parameters.
 	 */
-	params [0] = &space_iD_obj;
-	params [1] = &function_obj;
+	params [0] = &space_id_desc;
+	params [1] = &function_desc;
 	params [2] = NULL;
 
 	/*
 	 *  Set up the parameter objects
 	 */
-	space_iD_obj.common.type   = ACPI_TYPE_NUMBER;
-	space_iD_obj.number.value  = region_obj->region.space_id;
+	space_id_desc.common.type  = ACPI_TYPE_INTEGER;
+	space_id_desc.integer.value = region_obj->region.space_id;
 
-	function_obj.common.type   = ACPI_TYPE_NUMBER;
-	function_obj.number.value  = function;
+	function_desc.common.type  = ACPI_TYPE_INTEGER;
+	function_desc.integer.value = function;
 
 	/*
 	 *  Execute the method, no return value
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/events/evrgnini.c linux/drivers/acpi/events/evrgnini.c
--- v2.4.0/linux/drivers/acpi/events/evrgnini.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/events/evrgnini.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: evrgnini- ACPI Address_space (Op_region) init
- *              $Revision: 31 $
+ *              $Revision: 33 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/events/evsci.c linux/drivers/acpi/events/evsci.c
--- v2.4.0/linux/drivers/acpi/events/evsci.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/events/evsci.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: evsci - System Control Interrupt configuration and
  *                      legacy to ACPI mode state transition functions
- *              $Revision: 67 $
+ *              $Revision: 69 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/events/evxface.c linux/drivers/acpi/events/evxface.c
--- v2.4.0/linux/drivers/acpi/events/evxface.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/events/evxface.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: evxface - External interfaces for ACPI events
- *              $Revision: 97 $
+ *              $Revision: 101 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -187,26 +187,25 @@
 		return (AE_BAD_PARAMETER);
 	}
 
-	/* Convert and validate the device handle */
-
 	acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
 
+	/* Convert and validate the device handle */
+
 	device_node = acpi_ns_convert_handle_to_entry (device);
 	if (!device_node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
 	}
 
-
 	/*
-	 * Support for global notify handlers.  These handlers are invoked for
-	 * every notifiy of the type specifiec
+	 * Root Object:
+	 * ------------
+	 * Registering a notify handler on the root object indicates that the
+	 * caller wishes to receive notifications for all objects.  Note that
+	 * only one <external> global handler can be regsitered (per notify type).
 	 */
-
 	if (device == ACPI_ROOT_OBJECT) {
-		/*
-		 *  Make sure the handler is not already installed.
-		 */
+		/* Make sure the handler is not already installed */
 
 		if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
 			  acpi_gbl_sys_notify.handler) ||
@@ -222,94 +221,89 @@
 			acpi_gbl_sys_notify.handler = handler;
 			acpi_gbl_sys_notify.context = context;
 		}
-
-		else {
+		else /* ACPI_DEVICE_NOTIFY */ {
 			acpi_gbl_drv_notify.node = device_node;
 			acpi_gbl_drv_notify.handler = handler;
 			acpi_gbl_drv_notify.context = context;
 		}
 
-
 		/* Global notify handler installed */
-
-		goto unlock_and_exit;
 	}
 
-
 	/*
-	 * These are the ONLY objects that can receive ACPI notifications
+	 * Other Objects:
+	 * --------------
+	 * Caller will only receive notifications specific to the target object.
+	 * Note that only certain object types can receive notifications.
 	 */
-
-	if ((device_node->type != ACPI_TYPE_DEVICE)    &&
-		(device_node->type != ACPI_TYPE_PROCESSOR) &&
-		(device_node->type != ACPI_TYPE_POWER)     &&
-		(device_node->type != ACPI_TYPE_THERMAL))
-	{
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	/* Check for an existing internal object */
-
-	obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
-	if (obj_desc) {
+	else {
 		/*
-		 *  The object exists.
-		 *  Make sure the handler is not already installed.
+		 * These are the ONLY objects that can receive ACPI notifications
 		 */
-
-		if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
-			  obj_desc->device.sys_handler) ||
-			((handler_type == ACPI_DEVICE_NOTIFY) &&
-			  obj_desc->device.drv_handler))
+		if ((device_node->type != ACPI_TYPE_DEVICE)    &&
+			(device_node->type != ACPI_TYPE_PROCESSOR) &&
+			(device_node->type != ACPI_TYPE_POWER)     &&
+			(device_node->type != ACPI_TYPE_THERMAL))
 		{
-			status = AE_EXIST;
+			status = AE_BAD_PARAMETER;
 			goto unlock_and_exit;
 		}
-	}
 
-	else {
-		/* Create a new object */
+		/* Check for an existing internal object */
 
-		obj_desc = acpi_cm_create_internal_object (device_node->type);
-		if (!obj_desc) {
-			status = AE_NO_MEMORY;
-			goto unlock_and_exit;
+		obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
+		if (obj_desc) {
+
+			/* Object exists - make sure there's no handler */
+
+			if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
+				  obj_desc->device.sys_handler) ||
+				((handler_type == ACPI_DEVICE_NOTIFY) &&
+				  obj_desc->device.drv_handler))
+			{
+				status = AE_EXIST;
+				goto unlock_and_exit;
+			}
 		}
 
-		/* Attach new object to the Node */
+		else {
+			/* Create a new object */
 
-		status = acpi_ns_attach_object (device, obj_desc, (u8) device_node->type);
+			obj_desc = acpi_cm_create_internal_object (device_node->type);
+			if (!obj_desc) {
+				status = AE_NO_MEMORY;
+				goto unlock_and_exit;
+			}
 
-		if (ACPI_FAILURE (status)) {
-			goto unlock_and_exit;
-		}
-	}
+			/* Attach new object to the Node */
 
+			status = acpi_ns_attach_object (device, obj_desc, (u8) device_node->type);
 
-	/*
-	 *  If we get here, we know that there is no handler installed
-	 *  so let's party
-	 */
-	notify_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY);
-	if (!notify_obj) {
-		status = AE_NO_MEMORY;
-		goto unlock_and_exit;
-	}
+			if (ACPI_FAILURE (status)) {
+				goto unlock_and_exit;
+			}
+		}
 
-	notify_obj->notify_handler.node = device_node;
-	notify_obj->notify_handler.handler = handler;
-	notify_obj->notify_handler.context = context;
+		/* Install the handler */
 
+		notify_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY);
+		if (!notify_obj) {
+			status = AE_NO_MEMORY;
+			goto unlock_and_exit;
+		}
 
-	if (handler_type == ACPI_SYSTEM_NOTIFY) {
-		obj_desc->device.sys_handler = notify_obj;
-	}
+		notify_obj->notify_handler.node = device_node;
+		notify_obj->notify_handler.handler = handler;
+		notify_obj->notify_handler.context = context;
 
-	else {
-		obj_desc->device.drv_handler = notify_obj;
-	}
 
+		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+			obj_desc->device.sys_handler = notify_obj;
+		}
+		else /* ACPI_DEVICE_NOTIFY */ {
+			obj_desc->device.drv_handler = notify_obj;
+		}
+	}
 
 unlock_and_exit:
 	acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
@@ -343,7 +337,6 @@
 	ACPI_NAMESPACE_NODE     *device_node;
 	ACPI_STATUS             status = AE_OK;
 
-
 	/* Parameter validation */
 
 	if ((!handler) ||
@@ -363,62 +356,91 @@
 	}
 
 	/*
-	 * These are the ONLY objects that can receive ACPI notifications
+	 * Root Object:
+	 * ------------
 	 */
+	if (device == ACPI_ROOT_OBJECT) {
 
-	if ((device_node->type != ACPI_TYPE_DEVICE)    &&
-		(device_node->type != ACPI_TYPE_PROCESSOR) &&
-		(device_node->type != ACPI_TYPE_POWER)     &&
-		(device_node->type != ACPI_TYPE_THERMAL))
-	{
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	/* Check for an existing internal object */
+		if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
+			  !acpi_gbl_sys_notify.handler) ||
+			((handler_type == ACPI_DEVICE_NOTIFY) &&
+			  !acpi_gbl_drv_notify.handler))
+		{
+			status = AE_NOT_EXIST;
+			goto unlock_and_exit;
+		}
 
-	obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
-	if (!obj_desc) {
-		status = AE_NOT_EXIST;
-		goto unlock_and_exit;
+		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+			acpi_gbl_sys_notify.node = NULL;
+			acpi_gbl_sys_notify.handler = NULL;
+			acpi_gbl_sys_notify.context = NULL;
+		}
+		else {
+			acpi_gbl_drv_notify.node = NULL;
+			acpi_gbl_drv_notify.handler = NULL;
+			acpi_gbl_drv_notify.context = NULL;
+		}
 	}
 
 	/*
-	 *  The object exists.
-	 *
-	 *  Make sure the handler is installed.
+	 * Other Objects:
+	 * --------------
 	 */
-
-	if (handler_type == ACPI_SYSTEM_NOTIFY) {
-		notify_obj = obj_desc->device.sys_handler;
-	}
 	else {
-		notify_obj = obj_desc->device.drv_handler;
-	}
+		/*
+		 * These are the ONLY objects that can receive ACPI notifications
+		 */
+		if ((device_node->type != ACPI_TYPE_DEVICE)    &&
+			(device_node->type != ACPI_TYPE_PROCESSOR) &&
+			(device_node->type != ACPI_TYPE_POWER)     &&
+			(device_node->type != ACPI_TYPE_THERMAL))
+		{
+			status = AE_BAD_PARAMETER;
+			goto unlock_and_exit;
+		}
 
-	if ((!notify_obj) ||
-		(notify_obj->notify_handler.handler != handler))
-	{
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
+		/* Check for an existing internal object */
 
-	/*
-	 * Now we can remove the handler
-	 */
-	if (handler_type == ACPI_SYSTEM_NOTIFY) {
-		obj_desc->device.sys_handler = NULL;
-	}
-	else {
-		obj_desc->device.drv_handler = NULL;
+		obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
+		if (!obj_desc) {
+			status = AE_NOT_EXIST;
+			goto unlock_and_exit;
+		}
+
+		/* Object exists - make sure there's an existing handler */
+
+		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+			notify_obj = obj_desc->device.sys_handler;
+		}
+		else {
+			notify_obj = obj_desc->device.drv_handler;
+		}
+
+		if ((!notify_obj) ||
+			(notify_obj->notify_handler.handler != handler))
+		{
+			status = AE_BAD_PARAMETER;
+			goto unlock_and_exit;
+		}
+
+		/* Remove the handler */
+
+		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+			obj_desc->device.sys_handler = NULL;
+		}
+		else {
+			obj_desc->device.drv_handler = NULL;
+		}
+
+		acpi_cm_remove_reference (notify_obj);
 	}
 
-	acpi_cm_remove_reference (notify_obj);
 
 unlock_and_exit:
 	acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
 	return (status);
 }
+
 
 /******************************************************************************
  *
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/events/evxfevnt.c linux/drivers/acpi/events/evxfevnt.c
--- v2.4.0/linux/drivers/acpi/events/evxfevnt.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/events/evxfevnt.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
- *              $Revision: 26 $
+ *              $Revision: 28 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/events/evxfregn.c linux/drivers/acpi/events/evxfregn.c
--- v2.4.0/linux/drivers/acpi/events/evxfregn.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/events/evxfregn.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
  *                         Address Spaces.
- *              $Revision: 26 $
+ *              $Revision: 27 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/hardware/hwacpi.c linux/drivers/acpi/hardware/hwacpi.c
--- v2.4.0/linux/drivers/acpi/hardware/hwacpi.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/hardware/hwacpi.c	Mon Jan 29 10:15:58 2001
@@ -1,12 +1,13 @@
+
 /******************************************************************************
  *
- * Module Name: hwacpi - ACPI hardware functions - mode and timer
- *              $Revision: 34 $
+ * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
+ *              $Revision: 36 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -303,49 +304,4 @@
 	return (acpi_gbl_system_flags & SYS_MODES_MASK);
 }
 
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_hw_pmt_ticks
- *
- * PARAMETERS:  none
- *
- * RETURN:      Current value of the ACPI PMT (timer)
- *
- * DESCRIPTION: Obtains current value of ACPI PMT
- *
- ******************************************************************************/
-
-u32
-acpi_hw_pmt_ticks (void)
-{
-	u32                      ticks;
-
-	ticks = acpi_os_in32 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address));
-
-	return (ticks);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_hw_pmt_resolution
- *
- * PARAMETERS:  none
- *
- * RETURN:      Number of bits of resolution in the PMT (either 24 or 32)
- *
- * DESCRIPTION: Obtains resolution of the ACPI PMT (either 24bit or 32bit)
- *
- ******************************************************************************/
-
-u32
-acpi_hw_pmt_resolution (void)
-{
-	if (0 == acpi_gbl_FADT->tmr_val_ext) {
-		return (24);
-	}
-
-	return (32);
-}
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/hardware/hwcpu32.c linux/drivers/acpi/hardware/hwcpu32.c
--- v2.4.0/linux/drivers/acpi/hardware/hwcpu32.c	Mon Jan  1 10:23:20 2001
+++ linux/drivers/acpi/hardware/hwcpu32.c	Wed Dec 31 16:00:00 1969
@@ -1,711 +0,0 @@
-/******************************************************************************
- *
- * Name: hwcpu32.c - CPU support for IA32 (Throttling, Cx_states)
- *              $Revision: 39 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "acpi.h"
-#include "acnamesp.h"
-#include "achware.h"
-
-#define _COMPONENT          HARDWARE
-	 MODULE_NAME         ("Hwcpu32")
-
-
-#define BIT_4               0x10  /* TBD: [investigate] is this correct?  */
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_hw_enter_c1
- *
- * PARAMETERS:  Pblk_address    - Address of the processor control block
- *              Pm_timer_ticks  - Number of PM timer ticks elapsed while asleep
- *
- * RETURN:      Function status.
- *
- * DESCRIPTION: Set C1 state on IA32 processor (halt)
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_hw_enter_c1(
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     *pm_timer_ticks)
-{
-	u32                     timer = 0;
-
-
-	if (!pm_timer_ticks) {
-		/*
-		 * Enter C1:
-		 * ---------
-		 */
-		enable();
-		halt();
-		*pm_timer_ticks = ACPI_UINT32_MAX;
-	}
-	else {
-		timer = acpi_hw_pmt_ticks ();
-
-		/*
-		 * Enter C1:
-		 * ---------
-		 */
-		enable ();
-		halt ();
-
-		/*
-		 * Compute Time in C1:
-		 * -------------------
-		 */
-		timer = acpi_hw_pmt_ticks () - timer;
-
-		*pm_timer_ticks = timer;
-	}
-
-	return (AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_hw_enter_c2
- *
- * PARAMETERS:  Pblk_address    - Address of the processor control block
- *              Pm_timer_ticks  - Number of PM timer ticks elapsed while asleep
- *
- * RETURN:      <none>
- *
- * DESCRIPTION: Set C2 state on IA32 processor
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_hw_enter_c2(
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     *pm_timer_ticks)
-{
-	u32                     timer = 0;
-
-
-	if (!pblk_address || !pm_timer_ticks) {
-		return (AE_BAD_PARAMETER);
-	}
-
-	/*
-	 * Disable interrupts before all C2/C3 transitions.
-	 */
-	disable ();
-
-	timer = acpi_hw_pmt_ticks ();
-
-	/*
-	 * Enter C2:
-	 * ---------
-	 * Read from the P_LVL2 (P_BLK+4) register to invoke a C2 transition.
-	 */
-	acpi_os_in8 ((ACPI_IO_ADDRESS) (pblk_address + 4));
-
-	/*
-	 * Perform Dummy Op:
-	 * -----------------
-	 * We have to do something useless after reading LVL2 because chipsets
-	 * cannot guarantee that STPCLK# gets asserted in time to freeze execution.
-	 */
-	acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
-
-	/*
-	 * Compute Time in C2:
-	 * -------------------
-	 */
-	timer = acpi_hw_pmt_ticks () - timer;
-
-	*pm_timer_ticks = timer;
-
-	/*
-	 * Re-enable interrupts after coming out of C2/C3.
-	 */
-	enable ();
-
-	return (AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_hw_enter_c3
- *
- * PARAMETERS:  Pblk_address    - Address of the processor control block
- *              Pm_timer_ticks  - Number of PM timer ticks elapsed while asleep
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: Set C3 state on IA32 processor (UP only, cache coherency via
- *              disabling bus mastering)
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_hw_enter_c3(
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     *pm_timer_ticks)
-{
-	u32                     timer = 0;
-	u32                     bus_master_status = 0;
-
-
-	if (!pblk_address || !pm_timer_ticks) {
-		return (AE_BAD_PARAMETER);
-	}
-
-	/*
-	 * Check the BM_STS bit, if it is set, do not enter C3
-	 *  but clear the bit (with a write) and exit, telling
-	 *  the calling module that we spent zero time in C3.
-	 *  If bus mastering continues, this action should
-	 *  eventually cause a demotion to C2
-	 */
-	if (1 == (bus_master_status =
-		acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, BM_STS)))
-	{
-		/*
-		 * Clear the BM_STS bit by setting it.
-		 */
-		acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 1);
-		*pm_timer_ticks = 0;
-		return (AE_OK);
-	}
-
-	/*
-	 * Disable interrupts before all C2/C3 transitions.
-	 */
-	disable();
-
-	/*
-	 * Disable Bus Mastering:
-	 * ----------------------
-	 * Set the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits.
-	 */
-	 acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1);
-
-	/*
-	 * Get the timer base before entering C state
-	 */
-	timer = acpi_hw_pmt_ticks ();
-
-	/*
-	 * Enter C3:
-	 * ---------
-	 * Read from the P_LVL3 (P_BLK+5) register to invoke a C3 transition.
-	 */
-	acpi_os_in8 ((ACPI_IO_ADDRESS)(pblk_address + 5));
-
-	/*
-	 * Perform Dummy Op:
-	 * -----------------
-	 * We have to do something useless after reading LVL3 because chipsets
-	 * cannot guarantee that STPCLK# gets asserted in time to freeze execution.
-	 */
-	acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
-	/*
-	 * Immediately compute the time in the C state
-	 */
-	timer = acpi_hw_pmt_ticks() - timer;
-
-	/*
-	 * Re-Enable Bus Mastering:
-	 * ------------------------
-	 * Clear the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits.
-	 */
-	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 0);
-
-	/* TBD: [Unhandled]: Support 24-bit timers (this algorithm assumes 32-bit) */
-
-	*pm_timer_ticks = timer;
-
-	/*
-	 * Re-enable interrupts after coming out of C2/C3.
-	 */
-	enable();
-
-	return (AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_hw_enter_cx
- *
- * PARAMETERS:  Processor_handle    - handle of the processor
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: Invoke the currently active processor Cx handler to put this
- *              processor to sleep.
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_hw_enter_cx (
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     *pm_timer_ticks)
-{
-
-	if (!acpi_hw_cx_handlers[acpi_hw_active_cx_state]) {
-		return (AE_SUPPORT);
-	}
-
-	return (acpi_hw_cx_handlers[acpi_hw_active_cx_state] (pblk_address, pm_timer_ticks));
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_hw_set_cx
- *
- * PARAMETERS:  State               - value (1-3) of the Cx state to 'make active'
- *
- * RETURN:      Function status.
- *
- * DESCRIPTION: Sets the state to use during calls to Acpi_hw_enter_cx().
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_hw_set_cx (
-	u32                     cx_state)
-{
-	/*
-	 * Supported State?
-	 * ----------------
-	 */
-	if ((cx_state < 1) || (cx_state > 3)) {
-		return (AE_BAD_PARAMETER);
-	}
-
-	if (!acpi_hw_cx_handlers[cx_state]) {
-		return (AE_SUPPORT);
-	}
-
-	/*
-	 * New Cx State?
-	 * -------------
-	 * We only care when moving from one state to another...
-	 */
-	if (acpi_hw_active_cx_state == cx_state) {
-		return (AE_OK);
-	}
-
-	/*
-	 * Prepare to Use New State:
-	 * -------------------------
-	 * If the new Cx_state is C3, the BM_RLD bit must be set to allow
-	 *  the generation of a bus master requets to cause the processor
-	 *  in the C3 state to transition to the C0 state.
-	 */
-	switch (cx_state)
-	{
-	case 3:
-		acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 1);
-		break;
-	}
-
-	/*
-	 * Clean up from Old State:
-	 * ------------------------
-	 * If the old Cx_state was C3, the BM_RLD bit is reset. When the
-	 *  bit is reset, the generation of a bus master request does not
-	 *  effect any processor in the C3 state.
-	 */
-	switch (acpi_hw_active_cx_state)
-	{
-	case 3:
-		acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 0);
-		break;
-	}
-
-	/*
-	 * Enable:
-	 * -------
-	 */
-	acpi_hw_active_cx_state = cx_state;
-
-	return (AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_hw_get_cx_info
- *
- * PARAMETERS:  Cx_states       - Information (latencies) on all Cx states
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: This function is called both to initialize Cx handling
- *              and retrieve the current Cx information (latency values).
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_hw_get_cx_info (
-	u32                     cx_states[])
-{
-	u8                      SMP_system = FALSE;
-
-
-	if (!cx_states) {
-		return(AE_BAD_PARAMETER);
-	}
-
-	/*
-	 *  TBD: [Unhandled] need to init SMP_system using info from the MAPIC
-	 *       table.
-	 */
-
-	/*
-	 * Set Defaults:
-	 * -------------
-	 * C0 and C1 support is implied (but what about that PROC_C1 register
-	 * in the FADT?!?!).  Set C2/C3 to max. latency (not supported until
-	 * proven otherwise).
-	 */
-	cx_states[0] = 0;
-	cx_states[1] = 0;
-	cx_states[2] = MAX_CX_STATE_LATENCY;
-	cx_states[3] = MAX_CX_STATE_LATENCY;
-
-	/*
-	 * C2 Supported?
-	 * -------------
-	 * We're only supporting C2 when the latency is <= 100 microseconds,
-	 * and on SMP systems when P_LVL2_UP (which indicates C2 only on UP)
-	 * is not set.
-	 */
-	if (acpi_gbl_FADT->plvl2_lat <= 100) {
-		if (!SMP_system) {
-			acpi_hw_cx_handlers[2] = acpi_hw_enter_c2;
-			cx_states[2] = acpi_gbl_FADT->plvl2_lat;
-		}
-
-		else if (!acpi_gbl_FADT->plvl2_up) {
-			acpi_hw_cx_handlers[2] = acpi_hw_enter_c2;
-			cx_states[2] = acpi_gbl_FADT->plvl2_lat;
-		}
-	}
-
-	/*
-	 * C3 Supported?
-	 * -------------
-	 * We're only supporting C3 on UP systems when the latency is
-	 * <= 1000 microseconds and that include the ability to disable
-	 * Bus Mastering while in C3 (ARB_DIS) but allows Bus Mastering
-	 * requests to wake the system from C3 (BM_RLD).  Note his method
-	 * of maintaining cache coherency (disabling of bus mastering)
-	 * cannot be used on SMP systems, and flushing caches (e.g. WBINVD)
-	 * is simply too costly (at this time).
-	 */
-	if (acpi_gbl_FADT->plvl3_lat <= 1000) {
-		if (!SMP_system && (acpi_gbl_FADT->Xpm2_cnt_blk.address &&
-			acpi_gbl_FADT->pm2_cnt_len))
-		{
-			acpi_hw_cx_handlers[3] = acpi_hw_enter_c3;
-			cx_states[3] = acpi_gbl_FADT->plvl3_lat;
-		}
-	}
-
-	return(AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_hw_get_cx_handler
- *
- * PARAMETERS:  State           - the Cx state
- *              Handler         - pointer to location for the returned handler
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: This function is called to get an installed Cx state handler.
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_hw_get_cx_handler (
-	u32                     cx_state,
-	ACPI_C_STATE_HANDLER    *handler)
-{
-
-	if ((cx_state == 0) || (cx_state >= MAX_CX_STATES) || !handler) {
-		return(AE_BAD_PARAMETER);
-	}
-
-	*handler = acpi_hw_cx_handlers[cx_state];
-
-	return(AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_hw_set_cx_handler
- *
- * PARAMETERS:  Cx_state        - the Cx state
- *              Handler         - new Cx state handler
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: This function is called to install a new Cx state handler.
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_hw_set_cx_handler (
-	u32                     cx_state,
-	ACPI_C_STATE_HANDLER    handler)
-{
-
-	if ((cx_state == 0) || (cx_state >= MAX_CX_STATES) || !handler) {
-		return(AE_BAD_PARAMETER);
-	}
-
-	acpi_hw_cx_handlers[cx_state] = handler;
-
-	return(AE_OK);
-}
-
-
-/**************************************************************************
- *
- *  FUNCTION:    Acpi_hw_local_pow
- *
- *  PARAMETERS:  x,y operands
- *
- *  RETURN:      result
- *
- *  DESCRIPTION: Compute x ^ y
- *
- *************************************************************************/
-
-NATIVE_UINT
-acpi_hw_local_pow (
-	NATIVE_UINT             x,
-	NATIVE_UINT             y)
-{
-	NATIVE_UINT             i;
-	NATIVE_UINT             result = 1;
-
-
-	for (i = 0; i < y; i++) {
-		result = result * x;
-	}
-
-	return (result);
-}
-
-
-/**************************************************************************
- *
- *  FUNCTION:    Acpi_hw_enable_throttling
- *
- *  PARAMETERS:  Pblk_address       - Address of Pcnt (Processor Control)
- *                                      register
- *
- *  RETURN:      none
- *
- *  DESCRIPTION: Enable throttling by setting the THT_EN bit.
- *
- *************************************************************************/
-
-void
-acpi_hw_enable_throttling (
-	ACPI_IO_ADDRESS         pblk_address)
-{
-	u32                     pblk_value;
-
-
-	pblk_value = acpi_os_in32 (pblk_address);
-	pblk_value = pblk_value | BIT_4;
-	acpi_os_out32 (pblk_address, pblk_value);
-
-	return;
-}
-
-
-/**************************************************************************
- *
- *  FUNCTION:   Acpi_hw_disable_throttling
- *
- *  PARAMETERS: Pblk_address        - Address of Pcnt (Processor Control)
- *                                      register
- *
- *  RETURN:     none
- *
- *  DESCRIPTION:Disable throttling by clearing the THT_EN bit
- *
- *************************************************************************/
-
-void
-acpi_hw_disable_throttling (
-	ACPI_IO_ADDRESS         pblk_address)
-{
-	u32                     pblk_value;
-
-
-	pblk_value = acpi_os_in32 (pblk_address);
-	pblk_value = pblk_value & (~(u32)BIT_4);
-	acpi_os_out32 (pblk_address, pblk_value);
-
-	return;
-}
-
-
-/**************************************************************************
- *
- *  FUNCTION:    Acpi_hw_get_duty_cycle
- *
- *  PARAMETERS:  Duty_offset         Pcnt register duty cycle field offset
- *               Pblk_address        Pcnt register address in chipset
- *               Num_throttle_states # of CPU throttle states this system
- *                                      supports
- *
- *  RETURN:      none
- *
- *  DESCRIPTION: Get the duty cycle from the chipset
- *
- *************************************************************************/
-
-u32
-acpi_hw_get_duty_cycle (
-	u8                      duty_offset,
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     num_throttle_states)
-{
-	NATIVE_UINT             index;
-	u32                     duty32_value;
-	u32                     pcnt_mask_off_duty_field;
-
-
-	/*
-	 *  Use Num_throttle_states - 1 as mask [ex. 8 - 1 = 7 (Fh)]
-	 *  and then shift it into the right position
-	 */
-	pcnt_mask_off_duty_field = num_throttle_states - 1;
-
-	/*
-	 *  Read in the current value from the port
-	 */
-	duty32_value = acpi_os_in32 ((ACPI_IO_ADDRESS) pblk_address);
-
-	/*
-	 *  Shift the the value to LSB
-	 */
-	for (index = 0; index < (NATIVE_UINT) duty_offset; index++) {
-		duty32_value = duty32_value >> 1;
-	}
-
-	/*
-	 *  Get the duty field only
-	 */
-	duty32_value = duty32_value & pcnt_mask_off_duty_field;
-
-	return ((u32) duty32_value);
-}
-
-
-/**************************************************************************
- *
- * FUNCTION:    Acpi_hw_program_duty_cycle
- *
- * PARAMETERS:  Duty_offset         Pcnt register duty cycle field offset
- *              Duty_cycle          duty cycle to program into chipset
- *              Pblk_address        Pcnt register address in chipset
- *              Num_throttle_states # of CPU throttle states this system
- *                                      supports
- *
- * RETURN:      none
- *
- * DESCRIPTION: Program chipset with specified duty cycle by bit-shifting the
- *              duty cycle bits to the appropriate offset, reading the duty
- *              cycle register, OR-ing in the duty cycle, and writing it to
- *              the Pcnt register.
- *
- *************************************************************************/
-
-void
-acpi_hw_program_duty_cycle (
-	u8                      duty_offset,
-	u32                     duty_cycle,
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     num_throttle_states)
-{
-	NATIVE_UINT             index;
-	u32                     duty32_value;
-	u32                     pcnt_mask_off_duty_field;
-	u32                     port_value;
-
-
-	/*
-	 *  valid Duty_cycle passed
-	 */
-	duty32_value = duty_cycle;
-
-	/*
-	 *  use Num_throttle_states - 1 as mask [ex. 8 - 1 = 7 (Fh)]
-	 *  and then shift it into the right position
-	 */
-	pcnt_mask_off_duty_field = num_throttle_states - 1;
-
-	/*
-	 *  Shift the mask
-	 */
-	for (index = 0; index < (NATIVE_UINT) duty_offset; index++) {
-		pcnt_mask_off_duty_field = pcnt_mask_off_duty_field << 1;
-		duty32_value = duty32_value << 1;
-	}
-
-	/*
-	 *  Read in the current value from the port
-	 */
-	port_value = acpi_os_in32 ((ACPI_IO_ADDRESS) pblk_address);
-
-	/*
-	 *  Mask off the duty field so we don't OR in junk!
-	 */
-	port_value = port_value & (~pcnt_mask_off_duty_field);
-
-	/*
-	 *  OR in the bits we want to write out to the port
-	 */
-	port_value = (port_value | duty32_value) & (~(u32)BIT_4);
-
-	/*
-	 *  write it to the port
-	 */
-	acpi_os_out32 ((ACPI_IO_ADDRESS) pblk_address, port_value);
-
-	return;
-}
-
-
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/hardware/hwgpe.c linux/drivers/acpi/hardware/hwgpe.c
--- v2.4.0/linux/drivers/acpi/hardware/hwgpe.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/hardware/hwgpe.c	Mon Jan 29 10:15:58 2001
@@ -1,12 +1,13 @@
+
 /******************************************************************************
  *
  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
- *              $Revision: 25 $
+ *              $Revision: 28 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/hardware/hwregs.c linux/drivers/acpi/hardware/hwregs.c
--- v2.4.0/linux/drivers/acpi/hardware/hwregs.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/hardware/hwregs.c	Mon Jan 29 10:15:58 2001
@@ -3,12 +3,12 @@
  *
  * Module Name: hwregs - Read/write access functions for the various ACPI
  *                       control and status registers.
- *              $Revision: 86 $
+ *              $Revision: 88 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -37,7 +37,7 @@
 /* This matches the #defines in actypes.h. */
 
 NATIVE_CHAR                 *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_",
-			  "\\_S4_","\\_S4_b","\\_S5_"};
+			  "\\_S4_","\\_S5_","\\_S4_b"};
 
 
 /*******************************************************************************
@@ -53,7 +53,7 @@
  *
  ******************************************************************************/
 
-static u32
+u32
 acpi_hw_get_bit_shift (
 	u32                     mask)
 {
@@ -185,9 +185,9 @@
 	}
 
 	else if (((obj_desc->package.elements[0])->common.type !=
-			 ACPI_TYPE_NUMBER) ||
+			 ACPI_TYPE_INTEGER) ||
 			 ((obj_desc->package.elements[1])->common.type !=
-				ACPI_TYPE_NUMBER))
+				ACPI_TYPE_INTEGER))
 	{
 		/* Must have two  */
 
@@ -199,9 +199,9 @@
 		/*
 		 *  Valid _Sx_ package size, type, and value
 		 */
-		*slp_typ_a = (u8) (obj_desc->package.elements[0])->number.value;
+		*slp_typ_a = (u8) (obj_desc->package.elements[0])->integer.value;
 
-		*slp_typ_b = (u8) (obj_desc->package.elements[1])->number.value;
+		*slp_typ_b = (u8) (obj_desc->package.elements[1])->integer.value;
 	}
 
 
@@ -581,13 +581,8 @@
 
 	case PM1_CONTROL: /* 16-bit access */
 
-		if (register_id != SLP_TYPE_B) {
-			value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
-		}
-
-		if (register_id != SLP_TYPE_A) {
-			value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
-		}
+		value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
+		value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
 		break;
 
 
@@ -696,30 +691,20 @@
 
 	case PM1_CONTROL: /* 16-bit access */
 
-		/*
-		 * If SLP_TYP_A or SLP_TYP_B, only write to one reg block.
-		 * Otherwise, write to both.
-		 */
-		if (register_id == SLP_TYPE_A) {
-			acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
-		}
-		else if (register_id == SLP_TYPE_B) {
-			acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
-		}
-		else {
-			/* disable/re-enable interrupts if sleeping */
-			if (register_id == SLP_EN) {
-				disable();
-			}
+		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
+		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
+		break;
 
-			acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
-			acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
 
-			if (register_id == SLP_EN) {
-				enable();
-			}
-		}
+	case PM1_a_CONTROL: /* 16-bit access */
+
+		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
+		break;
+
+
+	case PM1_b_CONTROL: /* 16-bit access */
 
+		acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
 		break;
 
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/hardware/hwsleep.c linux/drivers/acpi/hardware/hwsleep.c
--- v2.4.0/linux/drivers/acpi/hardware/hwsleep.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/hardware/hwsleep.c	Mon Jan 29 10:15:58 2001
@@ -0,0 +1,189 @@
+
+/******************************************************************************
+ *
+ * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
+ *              $Revision: 5 $
+ *
+ *****************************************************************************/
+
+/*
+ *  Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "acpi.h"
+#include "acnamesp.h"
+#include "achware.h"
+
+#define _COMPONENT          HARDWARE
+	 MODULE_NAME         ("hwsleep")
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_set_firmware_waking_vector
+ *
+ * PARAMETERS:  Physical_address    - Physical address of ACPI real mode
+ *                                    entry point.
+ *
+ * RETURN:      AE_OK or AE_ERROR
+ *
+ * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_set_firmware_waking_vector (
+	ACPI_PHYSICAL_ADDRESS physical_address)
+{
+
+
+	/* Make sure that we have an FACS */
+
+	if (!acpi_gbl_FACS) {
+		return (AE_NO_ACPI_TABLES);
+	}
+
+	/* Set the vector */
+
+	if (acpi_gbl_FACS->vector_width == 32) {
+		* (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address;
+	}
+	else {
+		*acpi_gbl_FACS->firmware_waking_vector = physical_address;
+	}
+
+	return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_get_firmware_waking_vector
+ *
+ * PARAMETERS:  *Physical_address   - Output buffer where contents of
+ *                                    the Firmware_waking_vector field of
+ *                                    the FACS will be stored.
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_firmware_waking_vector (
+	ACPI_PHYSICAL_ADDRESS *physical_address)
+{
+
+
+	if (!physical_address) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	/* Make sure that we have an FACS */
+
+	if (!acpi_gbl_FACS) {
+		return (AE_NO_ACPI_TABLES);
+	}
+
+	/* Get the vector */
+
+	if (acpi_gbl_FACS->vector_width == 32) {
+		*physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector;
+	}
+	else {
+		*physical_address = *acpi_gbl_FACS->firmware_waking_vector;
+	}
+
+	return (AE_OK);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_enter_sleep_state
+ *
+ * PARAMETERS:  Sleep_state         - Which sleep state to enter
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_enter_sleep_state (
+	u8 sleep_state)
+{
+	ACPI_STATUS status;
+	ACPI_OBJECT_LIST arg_list;
+	ACPI_OBJECT arg;
+	u8 type_a;
+	u8 type_b;
+	u16 PM1_acontrol;
+	u16 PM1_bcontrol;
+
+	/*
+	 * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
+	 */
+
+	status = acpi_hw_obtain_sleep_type_register_data(sleep_state, &type_a, &type_b);
+
+	if (!ACPI_SUCCESS(status)) {
+		return status;
+	}
+
+	/* run the _PTS and _GTS methods */
+	MEMSET(&arg_list, 0, sizeof(arg_list));
+	arg_list.count = 1;
+	arg_list.pointer = &arg;
+
+	MEMSET(&arg, 0, sizeof(arg));
+	arg.type = ACPI_TYPE_INTEGER;
+	arg.integer.value = sleep_state;
+
+	acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
+	acpi_evaluate_object(NULL, "\\_GTS", &arg_list, NULL);
+
+	/* clear wake status */
+	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);
+
+	PM1_acontrol = (u16) acpi_hw_register_read(ACPI_MTX_LOCK, PM1_CONTROL);
+
+	/* mask off SLP_EN and SLP_TYP fields */
+	PM1_acontrol &= 0xC3FF;
+
+	/* mask in SLP_EN */
+	PM1_acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK));
+
+	PM1_bcontrol = PM1_acontrol;
+
+	/* mask in SLP_TYP */
+	PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
+	PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
+
+	/* the old version was disabling interrupts. let's try it without
+	 * and see how that works
+	 */
+	/*disable();*/
+
+	acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol);
+	acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol);
+
+	/*enable();*/
+
+	return (AE_OK);
+}
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/hardware/hwtimer.c linux/drivers/acpi/hardware/hwtimer.c
--- v2.4.0/linux/drivers/acpi/hardware/hwtimer.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/hardware/hwtimer.c	Mon Jan 29 10:15:58 2001
@@ -0,0 +1,196 @@
+
+/******************************************************************************
+ *
+ * Name: hwtimer.c - ACPI Power Management Timer Interface
+ *              $Revision: 4 $
+ *
+ *****************************************************************************/
+
+/*
+ *  Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "acpi.h"
+#include "achware.h"
+
+#define _COMPONENT          HARDWARE
+	 MODULE_NAME         ("hwtimer")
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_get_timer_resolution
+ *
+ * PARAMETERS:  none
+ *
+ * RETURN:      Number of bits of resolution in the PM Timer (24 or 32).
+ *
+ * DESCRIPTION: Obtains resolution of the ACPI PM Timer.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_timer_resolution (
+	u32                     *resolution)
+{
+	if (!resolution) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	if (0 == acpi_gbl_FADT->tmr_val_ext) {
+		*resolution = 24;
+	}
+	else {
+		*resolution = 32;
+	}
+
+	return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_get_timer
+ *
+ * PARAMETERS:  none
+ *
+ * RETURN:      Current value of the ACPI PM Timer (in ticks).
+ *
+ * DESCRIPTION: Obtains current value of ACPI PM Timer.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_timer (
+	u32                     *ticks)
+{
+	if (!ticks) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	*ticks = acpi_os_in32 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address));
+
+	return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_get_timer_duration
+ *
+ * PARAMETERS:  Start_ticks
+ *              End_ticks
+ *              Time_elapsed
+ *
+ * RETURN:      Time_elapsed
+ *
+ * DESCRIPTION: Computes the time elapsed (in microseconds) between two
+ *              PM Timer time stamps, taking into account the possibility of
+ *              rollovers, the timer resolution, and timer frequency.
+ *
+ *              The PM Timer's clock ticks at roughly 3.6 times per
+ *              _microsecond_, and its clock continues through Cx state
+ *              transitions (unlike many CPU timestamp counters) -- making it
+ *              a versatile and accurate timer.
+ *
+ *              Note that this function accomodates only a single timer
+ *              rollover.  Thus for 24-bit timers, this function should only
+ *              be used for calculating durations less than ~4.6 seconds
+ *              (~20 hours for 32-bit timers).
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_timer_duration (
+	u32                     start_ticks,
+	u32                     end_ticks,
+	u32                     *time_elapsed)
+{
+	u32                     delta_ticks = 0;
+	u32                     seconds = 0;
+	u32                     milliseconds = 0;
+	u32                     microseconds = 0;
+	u32                     remainder = 0;
+
+	if (!time_elapsed) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	/*
+	 * Compute Tick Delta:
+	 * -------------------
+	 * Handle timer rollovers on 24- versus 32-bit timers.
+	 */
+	if (start_ticks < end_ticks) {
+		delta_ticks = end_ticks - start_ticks;
+	}
+	else if (start_ticks > end_ticks) {
+		/* 24-bit Timer */
+		if (0 == acpi_gbl_FADT->tmr_val_ext) {
+			delta_ticks = (0x00FFFFFF - start_ticks) + end_ticks;
+		}
+		/* 32-bit Timer */
+		else {
+			delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
+		}
+	}
+
+	/*
+	 * Compute Duration:
+	 * -----------------
+	 * Since certain compilers (gcc/Linux, argh!) don't support 64-bit
+	 * divides in kernel-space we have to do some trickery to preserve
+	 * accuracy while using 32-bit math.
+	 *
+	 * TODO: Change to use 64-bit math when supported.
+	 *
+	 * The process is as follows:
+	 *  1. Compute the number of seconds by dividing Delta Ticks by
+	 *     the timer frequency.
+	 *  2. Compute the number of milliseconds in the remainder from step #1
+	 *     by multiplying by 1000 and then dividing by the timer frequency.
+	 *  3. Compute the number of microseconds in the remainder from step #2
+	 *     by multiplying by 1000 and then dividing by the timer frequency.
+	 *  4. Add the results from steps 1, 2, and 3 to get the total duration.
+	 *
+	 * Example: The time elapsed for Delta_ticks = 0xFFFFFFFF should be
+	 *          1199864031 microseconds.  This is computed as follows:
+	 *          Step #1: Seconds = 1199; Remainder = 3092840
+	 *          Step #2: Milliseconds = 864; Remainder = 113120
+	 *          Step #3: Microseconds = 31; Remainder = <don't care!>
+	 */
+
+	/* Step #1 */
+	seconds = delta_ticks / PM_TIMER_FREQUENCY;
+	remainder = delta_ticks % PM_TIMER_FREQUENCY;
+
+	/* Step #2 */
+	milliseconds = (remainder * 1000) / PM_TIMER_FREQUENCY;
+	remainder = (remainder * 1000) % PM_TIMER_FREQUENCY;
+
+	/* Step #3 */
+	microseconds = (remainder * 1000) / PM_TIMER_FREQUENCY;
+
+	/* Step #4 */
+	*time_elapsed = seconds * 1000000;
+	*time_elapsed += milliseconds * 1000;
+	*time_elapsed += microseconds;
+
+	return (AE_OK);
+}
+
+
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/hardware/hwxface.c linux/drivers/acpi/hardware/hwxface.c
--- v2.4.0/linux/drivers/acpi/hardware/hwxface.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/hardware/hwxface.c	Wed Dec 31 16:00:00 1969
@@ -1,595 +0,0 @@
-
-/******************************************************************************
- *
- * Name: hwxface.c - Hardware access external interfaces
- *              $Revision: 36 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "acpi.h"
-#include "acnamesp.h"
-#include "achware.h"
-
-#define _COMPONENT          HARDWARE
-	 MODULE_NAME         ("hwxface")
-
-
-/******************************************************************************
- *
- * Hardware globals
- *
- ******************************************************************************/
-
-
-ACPI_C_STATE_HANDLER        acpi_hw_cx_handlers[MAX_CX_STATES] =
-			  {NULL, acpi_hw_enter_c1, NULL, NULL};
-
-u32                         acpi_hw_active_cx_state = 1;
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_get_processor_throttling_info
- *
- * PARAMETERS:  Processor_handle    - handle for the cpu to get info about
- *              User_buffer         - caller supplied buffer
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: Get throttling capabilities for the processor, this routine
- *              builds the data directly into the callers buffer
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_get_processor_throttling_info (
-	ACPI_HANDLE             processor_handle,
-	ACPI_BUFFER             *user_buffer)
-{
-	NATIVE_UINT             percent_step;
-	NATIVE_UINT             next_percent;
-	NATIVE_UINT             num_throttle_states;
-	NATIVE_UINT             buffer_space_needed;
-	NATIVE_UINT             i;
-	u8                      duty_width;
-	ACPI_NAMESPACE_NODE     *cpu_node;
-	ACPI_OPERAND_OBJECT     *cpu_obj;
-	ACPI_CPU_THROTTLING_STATE *state_ptr;
-
-
-	/*
-	 *  Have to at least have a buffer to return info in
-	 */
-	if (!user_buffer) {
-		return(AE_BAD_PARAMETER);
-	}
-
-	/*
-	 *  Convert and validate the device handle
-	 */
-
-	cpu_node = acpi_ns_convert_handle_to_entry (processor_handle);
-	if (!cpu_node) {
-		return (AE_BAD_PARAMETER);
-	}
-
-   /*
-	*   Check for an existing internal object
-	*/
-
-	cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_node);
-	if (!cpu_obj) {
-		return (AE_NOT_FOUND);
-	}
-
-	/*
-	 * (Duty Width on IA-64 is zero)
-	 */
-	duty_width = acpi_gbl_FADT->duty_width;
-
-	/*
-	 *  P0 must always have a P_BLK all others may be null
-	 *  in either case, we can't throttle a processor that has no P_BLK
-	 *
-	 *  Also if no Duty width, one state and it is 100%
-	 *
-	 */
-	if (!cpu_obj->processor.length || !duty_width ||
-		(ACPI_UINT16_MAX < cpu_obj->processor.address))
-	{
-		/*
-		 *  Acpi_even though we can't throttle, we still have one state (100%)
-		 */
-		num_throttle_states = 1;
-	}
-
-	else {
-		num_throttle_states = (int) acpi_hw_local_pow (2,duty_width);
-	}
-
-	buffer_space_needed = num_throttle_states * sizeof (ACPI_CPU_THROTTLING_STATE);
-
-	if ((user_buffer->length < buffer_space_needed) || !user_buffer->pointer) {
-		user_buffer->length = buffer_space_needed;
-		return (AE_BUFFER_OVERFLOW);
-	}
-
-	user_buffer->length = buffer_space_needed;
-	state_ptr           = (ACPI_CPU_THROTTLING_STATE *) user_buffer->pointer;
-	percent_step        = 1000 / num_throttle_states;
-
-	/*
-	 * Build each entry in the buffer.  Note that we're using the value
-	 * 1000 and dividing each state by 10 to better avoid round-off
-	 * accumulation.  Also note that the throttling STATES are ordered
-	 * sequentially from 100% (state 0) on down (e.g. 87.5% = state 1),
-	 * which is exactly opposite from duty cycle values (12.5% = state 1).
-	 */
-	for (i = 0, next_percent = 1000; i < num_throttle_states; i++) {
-		state_ptr[i].state_number = i;
-		state_ptr[i].percent_of_clock = next_percent / 10;
-		next_percent -= percent_step;
-	}
-
-	return(AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_get_processor_throttling_state
- *
- * PARAMETERS:  Processor_handle    - handle for the cpu to throttle
- *              Throttle_state      - throttling state to enter
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: Get current hardware throttling state
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_get_processor_throttling_state (
-	ACPI_HANDLE             processor_handle,
-	u32                     *throttle_state)
-{
-	ACPI_NAMESPACE_NODE     *cpu_node;
-	ACPI_OPERAND_OBJECT     *cpu_obj;
-	u32                     num_throttle_states;
-	u32                     duty_cycle;
-	u8                      duty_offset;
-	u8                      duty_width;
-
-
-	/* Convert and validate the device handle */
-
-	cpu_node = acpi_ns_convert_handle_to_entry (processor_handle);
-	if (!cpu_node || !throttle_state) {
-		return (AE_BAD_PARAMETER);
-	}
-
-   /* Check for an existing internal object */
-
-	cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_node);
-	if (!cpu_obj) {
-		return (AE_NOT_FOUND);
-	}
-
-	/*
-	 * No Duty fields in IA64 tables
-	 */
-	duty_offset = acpi_gbl_FADT->duty_offset;
-	duty_width = acpi_gbl_FADT->duty_width;
-
-	/*
-	 *  Must have a valid P_BLK P0 must have a P_BLK all others may be null
-	 *  in either case, we can't thottle a processor that has no P_BLK
-	 *  that means we are in the only supported state (0 - 100%)
-	 *
-	 *  also, if Duty_width is zero there are no additional states
-	 */
-	if (!cpu_obj->processor.length || !duty_width ||
-		(ACPI_UINT16_MAX < cpu_obj->processor.address))
-	{
-		*throttle_state = 0;
-		return(AE_OK);
-	}
-
-	num_throttle_states = (u32) acpi_hw_local_pow (2,duty_width);
-
-	/*
-	 *  Get the current duty cycle value.
-	 */
-	duty_cycle = acpi_hw_get_duty_cycle (duty_offset,
-			   cpu_obj->processor.address,
-			   num_throttle_states);
-
-	/*
-	 * Convert duty cycle to throttling state (invert).
-	 */
-	if (duty_cycle == 0) {
-		*throttle_state = 0;
-	}
-
-	else {
-		*throttle_state = num_throttle_states - duty_cycle;
-	}
-
-	return(AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_set_processor_throttling_state
- *
- * PARAMETERS:  Processor_handle    - handle for the cpu to throttle
- *              Throttle_state      - throttling state to enter
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: Set hardware into requested throttling state, the handle
- *              passed in must have a valid P_BLK
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_set_processor_throttling_state (
-	ACPI_HANDLE             processor_handle,
-	u32                     throttle_state)
-{
-	ACPI_NAMESPACE_NODE    *cpu_node;
-	ACPI_OPERAND_OBJECT    *cpu_obj;
-	u32                     num_throttle_states = 0;
-	u8                      duty_offset;
-	u8                      duty_width;
-	u32                     duty_cycle = 0;
-
-
-	/* Convert and validate the device handle */
-
-	cpu_node = acpi_ns_convert_handle_to_entry (processor_handle);
-	if (!cpu_node) {
-		return (AE_BAD_PARAMETER);
-	}
-
-   /* Check for an existing internal object */
-
-	cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_node);
-	if (!cpu_obj) {
-		return (AE_NOT_FOUND);
-	}
-
-	/*
-	 * No Duty fields in IA64 tables
-	 */
-	duty_offset = acpi_gbl_FADT->duty_offset;
-	duty_width = acpi_gbl_FADT->duty_width;
-
-	/*
-	 *  Must have a valid P_BLK P0 must have a P_BLK all others may be null
-	 *  in either case, we can't thottle a processor that has no P_BLK
-	 *  that means we are in the only supported state (0 - 100%)
-	 *
-	 *  also, if Duty_width is zero there are no additional states
-	 */
-	if (!cpu_obj->processor.length || !duty_width ||
-		(ACPI_UINT16_MAX < cpu_obj->processor.address))
-	{
-		/*
-		 *  If caller wants to set the state to the only state we handle
-		 *  we're done.
-		 */
-		if (throttle_state == 0) {
-			return (AE_OK);
-		}
-
-		/*
-		 *  Can't set this state
-		 */
-		return (AE_SUPPORT);
-	}
-
-	num_throttle_states = (u32) acpi_hw_local_pow (2,duty_width);
-
-	/*
-	 * Convert throttling state to duty cycle (invert).
-	 */
-	if (throttle_state > 0) {
-		duty_cycle = num_throttle_states - throttle_state;
-	}
-
-	/*
-	 *  Turn off throttling (don't muck with the h/w while throttling).
-	 */
-	acpi_hw_disable_throttling (cpu_obj->processor.address);
-
-	/*
-	 *  Program the throttling state.
-	 */
-	acpi_hw_program_duty_cycle (duty_offset, duty_cycle,
-			 cpu_obj->processor.address, num_throttle_states);
-
-	/*
-	 *  Only enable throttling for non-zero states (0 - 100%)
-	 */
-	if (throttle_state) {
-		acpi_hw_enable_throttling (cpu_obj->processor.address);
-	}
-
-	return(AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_get_processor_cx_info
- *
- * PARAMETERS:  Processor_handle    - handle for the cpu return info about
- *              User_buffer         - caller supplied buffer
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: Get Cx state latencies, this routine
- *              builds the data directly into the callers buffer
- *
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_get_processor_cx_info (
-	ACPI_HANDLE             processor_handle,
-	ACPI_BUFFER             *user_buffer)
-{
-	ACPI_STATUS             status = AE_OK;
-	u32                     cx_state_latencies[4] = {0, 0, 0, 0};
-	NATIVE_UINT             buffer_space_needed = 0;
-	ACPI_CX_STATE           *state_ptr = NULL;
-	NATIVE_UINT             i = 0;
-
-
-	/*
-	 *  Have to at least have a buffer to return info in
-	 */
-	if (!user_buffer) {
-		return (AE_BAD_PARAMETER);
-	}
-
-	status = acpi_hw_get_cx_info (cx_state_latencies);
-	if (ACPI_FAILURE (status)) {
-		return (status);
-	}
-
-	buffer_space_needed = 4 * sizeof (ACPI_CX_STATE);
-
-	if ((user_buffer->length < buffer_space_needed) || !user_buffer->pointer) {
-		user_buffer->length = buffer_space_needed;
-		return (AE_BUFFER_OVERFLOW);
-	}
-
-	user_buffer->length = buffer_space_needed;
-
-	state_ptr = (ACPI_CX_STATE *) user_buffer->pointer;
-
-	for (i = 0; i < 4; i++) {
-		state_ptr[i].state_number = i;
-		state_ptr[i].latency = cx_state_latencies[i];
-	}
-
-	return (AE_OK);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_set_processor_sleep_state
- *
- * PARAMETERS:  Processor_handle    - handle for the cpu return info about
- *              Cx_state            - the Cx sleeping state (C1-C3) to make
- *                                      'active'
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: Sets which Cx state will be used during calls to
- *              Acpi_processor_sleep ()
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_set_processor_sleep_state (
-	ACPI_HANDLE             processor_handle,
-	u32                     cx_state)
-{
-	ACPI_STATUS             status;
-
-
-	status = acpi_hw_set_cx (cx_state);
-
-	return (status);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_processor_sleep
- *
- * PARAMETERS:  Processor_handle    - handle for the cpu to put to sleep (Cx)
- *              Time_sleeping       - time (in microseconds) elapsed while
- *                                      sleeping
- *
- * RETURN:      Status of function
- *
- * DESCRIPTION: Puts the processor into the currently active sleep state (Cx)
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_processor_sleep (
-	ACPI_HANDLE             processor_handle,
-	u32                     *pm_timer_ticks)
-{
-	ACPI_NAMESPACE_NODE     *cpu_node = NULL;
-	ACPI_OPERAND_OBJECT     *cpu_obj = NULL;
-	ACPI_IO_ADDRESS         address = 0;
-
-
-	/*
-	 * Convert Processor_handle to Pblk_addres...
-	 */
-
-	/* Convert and validate the device handle */
-
-	cpu_node = acpi_ns_convert_handle_to_entry (processor_handle);
-	if (!cpu_node) {
-		return (AE_BAD_PARAMETER);
-	}
-
-   /* Check for an existing internal object */
-
-	cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_node);
-	if (!cpu_obj) {
-		return (AE_NOT_FOUND);
-	}
-
-	/* Get the processor register block (P_BLK) address */
-
-	address = cpu_obj->processor.address;
-	if (!cpu_obj->processor.length) {
-		/* Ensure a NULL addresss (note that P_BLK isn't required for C1) */
-
-		address = 0;
-	}
-
-	/*
-	 * Enter the currently active Cx sleep state.
-	 */
-	return (acpi_hw_enter_cx (address, pm_timer_ticks));
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_get_timer
- *
- * PARAMETERS:  none
- *
- * RETURN:      Current value of the ACPI PMT (timer)
- *
- * DESCRIPTION: Obtains current value of ACPI PMT
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_get_timer (
-	u32                     *out_ticks)
-{
-
-	if (!out_ticks) {
-		return (AE_BAD_PARAMETER);
-	}
-
-	*out_ticks = acpi_hw_pmt_ticks ();
-
-	return (AE_OK);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_set_firmware_waking_vector
- *
- * PARAMETERS:  Physical_address    - Physical address of ACPI real mode
- *                                    entry point.
- *
- * RETURN:      AE_OK or AE_ERROR
- *
- * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_set_firmware_waking_vector (
-	ACPI_PHYSICAL_ADDRESS physical_address)
-{
-
-
-	/* Make sure that we have an FACS */
-
-	if (!acpi_gbl_FACS) {
-		return (AE_NO_ACPI_TABLES);
-	}
-
-	/* Set the vector */
-
-	if (acpi_gbl_FACS->vector_width == 32) {
-		* (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address;
-	}
-	else {
-		*acpi_gbl_FACS->firmware_waking_vector = physical_address;
-	}
-
-	return (AE_OK);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_get_firmware_waking_vector
- *
- * PARAMETERS:  *Physical_address   - Output buffer where contents of
- *                                    the Firmware_waking_vector field of
- *                                    the FACS will be stored.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_get_firmware_waking_vector (
-	ACPI_PHYSICAL_ADDRESS *physical_address)
-{
-
-
-	if (!physical_address) {
-		return (AE_BAD_PARAMETER);
-	}
-
-	/* Make sure that we have an FACS */
-
-	if (!acpi_gbl_FACS) {
-		return (AE_NO_ACPI_TABLES);
-	}
-
-	/* Get the vector */
-
-	if (acpi_gbl_FACS->vector_width == 32) {
-		*physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector;
-	}
-	else {
-		*physical_address = *acpi_gbl_FACS->firmware_waking_vector;
-	}
-
-	return (AE_OK);
-}
-
-
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/accommon.h linux/drivers/acpi/include/accommon.h
--- v2.4.0/linux/drivers/acpi/include/accommon.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/accommon.h	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: accommon.h -- prototypes for the common (subsystem-wide) procedures
- *       $Revision: 82 $
+ *       $Revision: 87 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -100,6 +100,8 @@
  * Cm_clib - Local implementations of C library functions
  */
 
+#ifndef ACPI_USE_SYSTEM_CLIBRARY
+
 NATIVE_UINT
 acpi_cm_strlen (
 	const NATIVE_CHAR       *string);
@@ -141,7 +143,7 @@
 acpi_cm_strtoul (
 	const NATIVE_CHAR       *string,
 	NATIVE_CHAR             **terminator,
-	u32                     base);
+	NATIVE_UINT             base);
 
 NATIVE_CHAR *
 acpi_cm_strstr (
@@ -161,7 +163,7 @@
 void *
 acpi_cm_memset (
 	void                    *dest,
-	u32                     value,
+	NATIVE_UINT             value,
 	NATIVE_UINT             count);
 
 u32
@@ -172,6 +174,7 @@
 acpi_cm_to_lower (
 	u32                     c);
 
+#endif /* ACPI_USE_SYSTEM_CLIBRARY */
 
 /*
  * Cm_copy - Object construction and conversion interfaces
@@ -297,7 +300,7 @@
 	u32                     line_number,
 	u32                     component_id,
 	NATIVE_CHAR             *function_name,
-	NATIVE_UINT             value);
+	ACPI_INTEGER            value);
 
 void
 function_ptr_exit (
@@ -596,7 +599,7 @@
 #define acpi_cm_callocate(a)            _cm_callocate(a, _COMPONENT,_THIS_MODULE,__LINE__)
 #define acpi_cm_free(a)                 _cm_free(a,_COMPONENT,_THIS_MODULE,__LINE__)
 
-#ifndef ACPI_DEBUG
+#ifndef ACPI_DEBUG_TRACK_ALLOCATIONS
 
 #define acpi_cm_add_element_to_alloc_list(a,b,c,d,e,f)
 #define acpi_cm_delete_element_from_alloc_list(a,b,c,d)
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acconfig.h linux/drivers/acpi/include/acconfig.h
--- v2.4.0/linux/drivers/acpi/include/acconfig.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acconfig.h	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acconfig.h - Global configuration constants
- *       $Revision: 48 $
+ *       $Revision: 53 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -53,7 +53,7 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION             __DATE__
+#define ACPI_CA_VERSION             0x20010125
 
 
 /* Maximum objects in the various object caches */
@@ -121,6 +121,10 @@
 
 #define MTH_NUM_ARGS                7
 #define MTH_MAX_ARG                 6
+
+/* Maximum length of resulting string when converting from a buffer */
+
+#define ACPI_MAX_STRING_CONVERSION  200
 
 /*
  * Operand Stack (in WALK_STATE), Must be large enough to contain MTH_MAX_ARG
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acdebug.h linux/drivers/acpi/include/acdebug.h
--- v2.4.0/linux/drivers/acpi/include/acdebug.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acdebug.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acdebug.h - ACPI/AML debugger
- *       $Revision: 37 $
+ *       $Revision: 39 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acdispat.h linux/drivers/acpi/include/acdispat.h
--- v2.4.0/linux/drivers/acpi/include/acdispat.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acdispat.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acdispat.h - dispatcher (parser to interpreter interface)
- *       $Revision: 33 $
+ *       $Revision: 35 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acenv.h linux/drivers/acpi/include/acenv.h
--- v2.4.0/linux/drivers/acpi/include/acenv.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acenv.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acenv.h - Generation environment specific items
- *       $Revision: 65 $
+ *       $Revision: 70 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 
 
 /*
- * Configuration for ACPI Utilities
+ * Configuration for ACPI tools and utilities
  */
 
 #ifdef _ACPI_DUMP_APP
@@ -55,6 +55,16 @@
 #define ACPI_USE_SYSTEM_CLIBRARY
 #endif
 
+/*
+ * Memory allocation tracking.  Used only if
+ * 1) This is the debug version
+ * 2) This is NOT a 16-bit version of the code (not enough real-mode memory)
+ */
+#ifdef ACPI_DEBUG
+#ifndef _IA16
+#define ACPI_DEBUG_TRACK_ALLOCATIONS
+#endif
+#endif
 
 /*
  * Environment configuration.  The purpose of this file is to interface to the
@@ -154,17 +164,17 @@
 #define STRUPR(s)       strupr((s))
 #define STRLEN(s)       strlen((s))
 #define STRCPY(d,s)     strcpy((d), (s))
-#define STRNCPY(d,s,n)  strncpy((d), (s), (n))
-#define STRNCMP(d,s,n)  strncmp((d), (s), (n))
+#define STRNCPY(d,s,n)  strncpy((d), (s), (NATIVE_INT)(n))
+#define STRNCMP(d,s,n)  strncmp((d), (s), (NATIVE_INT)(n))
 #define STRCMP(d,s)     strcmp((d), (s))
 #define STRCAT(d,s)     strcat((d), (s))
-#define STRNCAT(d,s,n)  strncat((d), (s), (n))
-#define STRTOUL(d,s,n)  strtoul((d), (s), (n))
-#define MEMCPY(d,s,n)   memcpy((d), (s), (n))
-#define MEMSET(d,s,n)   memset((d), (s), (n))
+#define STRNCAT(d,s,n)  strncat((d), (s), (NATIVE_INT)(n))
+#define STRTOUL(d,s,n)  strtoul((d), (s), (NATIVE_INT)(n))
+#define MEMCPY(d,s,n)   memcpy((d), (s), (NATIVE_INT)(n))
+#define MEMSET(d,s,n)   memset((d), (s), (NATIVE_INT)(n))
 #define TOUPPER         toupper
 #define TOLOWER         tolower
-
+#define IS_XDIGIT       isxdigit
 
 /******************************************************************************
  *
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acevents.h linux/drivers/acpi/include/acevents.h
--- v2.4.0/linux/drivers/acpi/include/acevents.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acevents.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acevents.h - Event subcomponent prototypes and defines
- *       $Revision: 62 $
+ *       $Revision: 63 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acexcep.h linux/drivers/acpi/include/acexcep.h
--- v2.4.0/linux/drivers/acpi/include/acexcep.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acexcep.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acexcep.h - Exception codes returned by the ACPI subsystem
- *       $Revision: 37 $
+ *       $Revision: 41 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -116,8 +116,10 @@
 #define AE_AML_NAME_NOT_FOUND           (ACPI_STATUS) (0x0010 | AE_CODE_AML)
 #define AE_AML_INTERNAL                 (ACPI_STATUS) (0x0011 | AE_CODE_AML)
 #define AE_AML_INVALID_SPACE_ID         (ACPI_STATUS) (0x0012 | AE_CODE_AML)
+#define AE_AML_STRING_LIMIT             (ACPI_STATUS) (0x0013 | AE_CODE_AML)
+#define AE_AML_NO_RETURN_VALUE          (ACPI_STATUS) (0x0014 | AE_CODE_AML)
 
-#define AE_CODE_AML_MAX                 0x0012
+#define AE_CODE_AML_MAX                 0x0014
 
 /*
  * Internal exceptions used for control
@@ -202,6 +204,8 @@
 	"AE_AML_NAME_NOT_FOUND",
 	"AE_AML_INTERNAL",
 	"AE_AML_INVALID_SPACE_ID",
+	"AE_AML_STRING_LIMIT",
+	"AE_AML_NO_RETURN_VALUE",
 };
 
 static NATIVE_CHAR          *acpi_gbl_exception_names_ctrl[] =
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acgcc.h linux/drivers/acpi/include/acgcc.h
--- v2.4.0/linux/drivers/acpi/include/acgcc.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acgcc.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acgcc.h - GCC specific defines, etc.
- *       $Revision: 2 $
+ *       $Revision: 4 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acglobal.h linux/drivers/acpi/include/acglobal.h
--- v2.4.0/linux/drivers/acpi/include/acglobal.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acglobal.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acglobal.h - Declarations for global variables
- *       $Revision: 92 $
+ *       $Revision: 96 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -154,7 +154,6 @@
 ACPI_EXTERN u8                          acpi_gbl_step_to_next_call;
 ACPI_EXTERN u8                          acpi_gbl_acpi_hardware_present;
 
-
 ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER  acpi_gbl_drv_notify;
 ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER  acpi_gbl_sys_notify;
 
@@ -162,7 +161,8 @@
 extern      u8                          acpi_gbl_shutdown;
 extern      u32                         acpi_gbl_system_flags;
 extern      u32                         acpi_gbl_startup_flags;
-extern      u8                          acpi_gbl_decode_to8bit[];
+extern      u8                          acpi_gbl_decode_to8bit[8];
+extern NATIVE_CHAR                      acpi_gbl_hex_to_ascii[];
 
 
 /*****************************************************************************
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/achware.h linux/drivers/acpi/include/achware.h
--- v2.4.0/linux/drivers/acpi/include/achware.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/achware.h	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: achware.h -- hardware specific interfaces
- *       $Revision: 48 $
+ *       $Revision: 53 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -27,6 +27,10 @@
 #define __ACHWARE_H__
 
 
+/* PM Timer ticks per second (HZ) */
+#define PM_TIMER_FREQUENCY  3579545
+
+
 /* Prototypes */
 
 
@@ -92,6 +96,10 @@
 acpi_hw_clear_acpi_status (
    void);
 
+u32
+acpi_hw_get_bit_shift (
+	u32                     mask);
+
 
 /* GPE support */
 
@@ -121,89 +129,21 @@
 	u8                      *slp_typ_b);
 
 
-/* Cx State Prototypes */
-
-ACPI_STATUS
-acpi_hw_enter_c1(
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     *pm_timer_ticks);
-
-ACPI_STATUS
-acpi_hw_enter_c2(
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     *pm_timer_ticks);
-
-ACPI_STATUS
-acpi_hw_enter_c3(
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     *pm_timer_ticks);
-
-ACPI_STATUS
-acpi_hw_enter_cx (
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     *pm_timer_ticks);
-
-ACPI_STATUS
-acpi_hw_set_cx (
-	u32                     cx_state);
-
-ACPI_STATUS
-acpi_hw_get_cx_info (
-	u32                     cx_states[]);
+/* ACPI Timer prototypes */
 
 ACPI_STATUS
-acpi_hw_get_cx_handler (
-	u32                     cx_state,
-	ACPI_C_STATE_HANDLER    *handler);
+acpi_get_timer_resolution (
+	u32                     *resolution);
 
 ACPI_STATUS
-acpi_hw_set_cx_handler (
-	u32                     cx_state,
-	ACPI_C_STATE_HANDLER    handler);
-
-
-/* Throttling Prototypes */
-
-void
-acpi_hw_enable_throttling (
-	ACPI_IO_ADDRESS         pblk_address);
-
-void
-acpi_hw_disable_throttling (
-	ACPI_IO_ADDRESS         pblk_address);
-
-u32
-acpi_hw_get_duty_cycle (
-	u8                      duty_offset,
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     num_throttle_states);
-
-void
-acpi_hw_program_duty_cycle (
-	u8                      duty_offset,
-	u32                     duty_cycle,
-	ACPI_IO_ADDRESS         pblk_address,
-	u32                     num_throttle_states);
-
-NATIVE_UINT
-acpi_hw_local_pow (
-	NATIVE_UINT             x,
-	NATIVE_UINT             y);
-
-
-/* ACPI Timer prototypes */
-
-u32
-acpi_hw_pmt_ticks (
-	void);
-
-u32
-acpi_hw_pmt_resolution (
-	void);
+acpi_get_timer (
+	u32                     *ticks);
 
 ACPI_STATUS
-acpi_get_timer (
-	u32                     *out_ticks);
+acpi_get_timer_duration (
+	u32                     start_ticks,
+	u32                     end_ticks,
+	u32                     *time_elapsed);
 
 
 #endif /* __ACHWARE_H__ */
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acinterp.h linux/drivers/acpi/include/acinterp.h
--- v2.4.0/linux/drivers/acpi/include/acinterp.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acinterp.h	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acinterp.h - Interpreter subcomponent prototypes and defines
- *       $Revision: 86 $
+ *       $Revision: 91 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -70,9 +70,34 @@
 
 
 /*
- * amfield - ACPI AML (p-code) execution - field manipulation
+ * amconvrt - object conversion
  */
 
+ACPI_STATUS
+acpi_aml_convert_to_integer (
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state);
+
+ACPI_STATUS
+acpi_aml_convert_to_buffer (
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state);
+
+ACPI_STATUS
+acpi_aml_convert_to_string (
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state);
+
+ACPI_STATUS
+acpi_aml_convert_to_target_type (
+	OBJECT_TYPE_INTERNAL    destination_type,
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state);
+
+
+/*
+ * amfield - ACPI AML (p-code) execution - field manipulation
+ */
 
 ACPI_STATUS
 acpi_aml_read_field (
@@ -419,17 +444,75 @@
 	ACPI_WALK_STATE         *walk_state);
 
 ACPI_STATUS
-acpi_aml_store_object_to_object (
+acpi_aml_store_object_to_index (
 	ACPI_OPERAND_OBJECT     *val_desc,
 	ACPI_OPERAND_OBJECT     *dest_desc,
 	ACPI_WALK_STATE         *walk_state);
 
 ACPI_STATUS
 acpi_aml_store_object_to_node (
-	ACPI_OPERAND_OBJECT     *val_desc,
+	ACPI_OPERAND_OBJECT     *source_desc,
 	ACPI_NAMESPACE_NODE     *node,
 	ACPI_WALK_STATE         *walk_state);
 
+ACPI_STATUS
+acpi_aml_store_object_to_object (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *dest_desc,
+	ACPI_WALK_STATE         *walk_state);
+
+
+/*
+ *
+ */
+
+ACPI_STATUS
+acpi_aml_resolve_object (
+	ACPI_OPERAND_OBJECT     **source_desc_ptr,
+	OBJECT_TYPE_INTERNAL    target_type,
+	ACPI_WALK_STATE         *walk_state);
+
+ACPI_STATUS
+acpi_aml_store_object (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	OBJECT_TYPE_INTERNAL    target_type,
+	ACPI_OPERAND_OBJECT     **target_desc_ptr,
+	ACPI_WALK_STATE         *walk_state);
+
+
+/*
+ * amcopy - object copy
+ */
+
+ACPI_STATUS
+acpi_aml_copy_buffer_to_buffer (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc);
+
+ACPI_STATUS
+acpi_aml_copy_string_to_string (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc);
+
+ACPI_STATUS
+acpi_aml_copy_integer_to_index_field (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc);
+
+ACPI_STATUS
+acpi_aml_copy_integer_to_bank_field (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc);
+
+ACPI_STATUS
+acpi_aml_copy_data_to_named_field (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_NAMESPACE_NODE     *node);
+
+ACPI_STATUS
+acpi_aml_copy_integer_to_field_unit (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc);
 
 /*
  * amutils - interpreter/scanner utilities
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/aclinux.h linux/drivers/acpi/include/aclinux.h
--- v2.4.0/linux/drivers/acpi/include/aclinux.h	Fri Dec 29 14:21:48 2000
+++ linux/drivers/acpi/include/aclinux.h	Wed Jan 24 15:28:36 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: aclinux.h - OS specific defines, etc.
- *       $Revision: 6 $
+ *       $Revision: 7 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/aclocal.h linux/drivers/acpi/include/aclocal.h
--- v2.4.0/linux/drivers/acpi/include/aclocal.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/aclocal.h	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: aclocal.h - Internal data types used across the ACPI subsystem
- *       $Revision: 95 $
+ *       $Revision: 100 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -74,7 +74,7 @@
 #define NUM_MTX                     MAX_MTX+1
 
 
-#ifdef ACPI_DEBUG
+#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER)
 #ifdef DEFINE_ACPI_GLOBALS
 
 /* Names for the mutexes used in the subsystem */
@@ -476,7 +476,9 @@
 	u32                     parse_args;     /* Grammar/Parse time arguments */
 	u32                     runtime_args;   /* Interpret time arguments */
 
-	DEBUG_ONLY_MEMBERS (NATIVE_CHAR *name)  /* op name (debug only) */
+#ifdef _OPCODE_NAMES
+	NATIVE_CHAR             *name;          /* op name (debug only) */
+#endif
 
 } ACPI_OPCODE_INFO;
 
@@ -591,6 +593,7 @@
 	ACPI_GENERIC_STATE      *scope_info;                        /* Stack of nested scopes */
 	ACPI_PARSE_STATE        *parser_state;                      /* Current state of parser */
 	u8                      *aml_last_while;
+	ACPI_OPCODE_INFO        *op_info;                           /* Info on current opcode */
 	ACPI_PARSE_DOWNWARDS    descending_callback;
 	ACPI_PARSE_UPWARDS      ascending_callback;
 
@@ -605,6 +608,7 @@
 	u32                     parse_flags;
 	u8                      walk_type;
 	u8                      return_used;
+	u16                     opcode;                             /* Current AML opcode */
 	u32                     prev_arg_types;
 
 	/* Debug support */
@@ -728,14 +732,16 @@
 #define PM1_STS                     0x0100
 #define PM1_EN                      0x0200
 #define PM1_CONTROL                 0x0300
-#define PM2_CONTROL                 0x0400
-#define PM_TIMER                    0x0500
-#define PROCESSOR_BLOCK             0x0600
-#define GPE0_STS_BLOCK              0x0700
-#define GPE0_EN_BLOCK               0x0800
-#define GPE1_STS_BLOCK              0x0900
-#define GPE1_EN_BLOCK               0x0A00
-#define SMI_CMD_BLOCK               0x0B00
+#define PM1_a_CONTROL               0x0400
+#define PM1_b_CONTROL               0x0500
+#define PM2_CONTROL                 0x0600
+#define PM_TIMER                    0x0700
+#define PROCESSOR_BLOCK             0x0800
+#define GPE0_STS_BLOCK              0x0900
+#define GPE0_EN_BLOCK               0x0A00
+#define GPE1_STS_BLOCK              0x0B00
+#define GPE1_EN_BLOCK               0x0C00
+#define SMI_CMD_BLOCK               0x0D00
 
 /*
  * Address space bitmasks for mmio or io spaces
@@ -751,66 +757,66 @@
 /*
  * Control bit definitions
  */
-#define TMR_STS     (PM1_STS | 0x01)
-#define BM_STS      (PM1_STS | 0x02)
-#define GBL_STS     (PM1_STS | 0x03)
-#define PWRBTN_STS  (PM1_STS | 0x04)
-#define SLPBTN_STS  (PM1_STS | 0x05)
-#define RTC_STS     (PM1_STS | 0x06)
-#define WAK_STS     (PM1_STS | 0x07)
+#define TMR_STS                     (PM1_STS | 0x01)
+#define BM_STS                      (PM1_STS | 0x02)
+#define GBL_STS                     (PM1_STS | 0x03)
+#define PWRBTN_STS                  (PM1_STS | 0x04)
+#define SLPBTN_STS                  (PM1_STS | 0x05)
+#define RTC_STS                     (PM1_STS | 0x06)
+#define WAK_STS                     (PM1_STS | 0x07)
 
-#define TMR_EN      (PM1_EN | 0x01)
+#define TMR_EN                      (PM1_EN | 0x01)
 			   /* no BM_EN */
-#define GBL_EN      (PM1_EN | 0x03)
-#define PWRBTN_EN   (PM1_EN | 0x04)
-#define SLPBTN_EN   (PM1_EN | 0x05)
-#define RTC_EN      (PM1_EN | 0x06)
-#define WAK_EN      (PM1_EN | 0x07)
-
-#define SCI_EN      (PM1_CONTROL | 0x01)
-#define BM_RLD      (PM1_CONTROL | 0x02)
-#define GBL_RLS     (PM1_CONTROL | 0x03)
-#define SLP_TYPE_A  (PM1_CONTROL | 0x04)
-#define SLP_TYPE_B  (PM1_CONTROL | 0x05)
-#define SLP_EN      (PM1_CONTROL | 0x06)
-
-#define ARB_DIS     (PM2_CONTROL | 0x01)
-
-#define TMR_VAL     (PM_TIMER | 0x01)
-
-#define GPE0_STS    (GPE0_STS_BLOCK | 0x01)
-#define GPE0_EN     (GPE0_EN_BLOCK  | 0x01)
-
-#define GPE1_STS    (GPE1_STS_BLOCK | 0x01)
-#define GPE1_EN     (GPE1_EN_BLOCK  | 0x01)
-
-
-#define TMR_STS_MASK        0x0001
-#define BM_STS_MASK         0x0010
-#define GBL_STS_MASK        0x0020
-#define PWRBTN_STS_MASK     0x0100
-#define SLPBTN_STS_MASK     0x0200
-#define RTC_STS_MASK        0x0400
-#define WAK_STS_MASK        0x8000
-
-#define ALL_FIXED_STS_BITS  (TMR_STS_MASK   | BM_STS_MASK  | GBL_STS_MASK \
-					   | PWRBTN_STS_MASK | SLPBTN_STS_MASK \
-					   | RTC_STS_MASK | WAK_STS_MASK)
-
-#define TMR_EN_MASK         0x0001
-#define GBL_EN_MASK         0x0020
-#define PWRBTN_EN_MASK      0x0100
-#define SLPBTN_EN_MASK      0x0200
-#define RTC_EN_MASK         0x0400
-
-#define SCI_EN_MASK         0x0001
-#define BM_RLD_MASK         0x0002
-#define GBL_RLS_MASK        0x0004
-#define SLP_TYPE_X_MASK     0x1C00
-#define SLP_EN_MASK         0x2000
+#define GBL_EN                      (PM1_EN | 0x03)
+#define PWRBTN_EN                   (PM1_EN | 0x04)
+#define SLPBTN_EN                   (PM1_EN | 0x05)
+#define RTC_EN                      (PM1_EN | 0x06)
+#define WAK_EN                      (PM1_EN | 0x07)
+
+#define SCI_EN                      (PM1_CONTROL | 0x01)
+#define BM_RLD                      (PM1_CONTROL | 0x02)
+#define GBL_RLS                     (PM1_CONTROL | 0x03)
+#define SLP_TYPE_A                  (PM1_CONTROL | 0x04)
+#define SLP_TYPE_B                  (PM1_CONTROL | 0x05)
+#define SLP_EN                      (PM1_CONTROL | 0x06)
+
+#define ARB_DIS                     (PM2_CONTROL | 0x01)
+
+#define TMR_VAL                     (PM_TIMER | 0x01)
+
+#define GPE0_STS                    (GPE0_STS_BLOCK | 0x01)
+#define GPE0_EN                     (GPE0_EN_BLOCK  | 0x01)
+
+#define GPE1_STS                    (GPE1_STS_BLOCK | 0x01)
+#define GPE1_EN                     (GPE1_EN_BLOCK  | 0x01)
+
+
+#define TMR_STS_MASK                0x0001
+#define BM_STS_MASK                 0x0010
+#define GBL_STS_MASK                0x0020
+#define PWRBTN_STS_MASK             0x0100
+#define SLPBTN_STS_MASK             0x0200
+#define RTC_STS_MASK                0x0400
+#define WAK_STS_MASK                0x8000
+
+#define ALL_FIXED_STS_BITS          (TMR_STS_MASK   | BM_STS_MASK  | GBL_STS_MASK \
+					 | PWRBTN_STS_MASK | SLPBTN_STS_MASK \
+					 | RTC_STS_MASK | WAK_STS_MASK)
+
+#define TMR_EN_MASK                 0x0001
+#define GBL_EN_MASK                 0x0020
+#define PWRBTN_EN_MASK              0x0100
+#define SLPBTN_EN_MASK              0x0200
+#define RTC_EN_MASK                 0x0400
+
+#define SCI_EN_MASK                 0x0001
+#define BM_RLD_MASK                 0x0002
+#define GBL_RLS_MASK                0x0004
+#define SLP_TYPE_X_MASK             0x1C00
+#define SLP_EN_MASK                 0x2000
 
-#define ARB_DIS_MASK        0x0001
-#define TMR_VAL_MASK        0xFFFFFFFF
+#define ARB_DIS_MASK                0x0001
+#define TMR_VAL_MASK                0xFFFFFFFF
 
 #define GPE0_STS_MASK
 #define GPE0_EN_MASK
@@ -819,8 +825,8 @@
 #define GPE1_EN_MASK
 
 
-#define ACPI_READ           1
-#define ACPI_WRITE          2
+#define ACPI_READ                   1
+#define ACPI_WRITE                  2
 
 
 /* Plug and play */
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acmacros.h linux/drivers/acpi/include/acmacros.h
--- v2.4.0/linux/drivers/acpi/include/acmacros.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acmacros.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acmacros.h - C macros for the entire subsystem.
- *       $Revision: 59 $
+ *       $Revision: 62 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -30,6 +30,14 @@
  * Data manipulation macros
  */
 
+#ifndef LODWORD
+#define LODWORD(l)                      ((u32)(UINT64)(l))
+#endif
+
+#ifndef HIDWORD
+#define HIDWORD(l)                      ((u32)((((UINT64)(l)) >> 32) & 0xFFFFFFFF))
+#endif
+
 #ifndef LOWORD
 #define LOWORD(l)                       ((u16)(NATIVE_UINT)(l))
 #endif
@@ -64,10 +72,18 @@
 
 
 #ifdef _IA16
+/*
+ * For 16-bit addresses, we have to assume that the upper 32 bits
+ * are zero.
+ */
 #define ACPI_GET_ADDRESS(a)             ((a).lo)
 #define ACPI_STORE_ADDRESS(a,b)         {(a).hi=0;(a).lo=(b);}
-#define ACPI_VALID_ADDRESS(a)           ((a).hi && (a).lo)
+#define ACPI_VALID_ADDRESS(a)           ((a).hi | (a).lo)
+
 #else
+/*
+ * Full 64-bit address on 32-bit and 64-bit platforms
+ */
 #define ACPI_GET_ADDRESS(a)             (a)
 #define ACPI_STORE_ADDRESS(a,b)         ((a)=(b))
 #define ACPI_VALID_ADDRESS(a)           (a)
@@ -335,7 +351,7 @@
  */
 #define return_VOID                     {function_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name);return;}
 #define return_ACPI_STATUS(s)           {function_status_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,s);return(s);}
-#define return_VALUE(s)                 {function_value_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(NATIVE_UINT)s);return(s);}
+#define return_VALUE(s)                 {function_value_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(ACPI_INTEGER)s);return(s);}
 #define return_PTR(s)                   {function_ptr_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(u8 *)s);return(s);}
 
 
@@ -346,6 +362,8 @@
 
 #define DEBUG_DEFINE(a)                 a;
 #define DEBUG_ONLY_MEMBERS(a)           a;
+#define _OPCODE_NAMES
+#define _VERBOSE_STRUCTURES
 
 
 /* Stack and buffer dumping */
@@ -458,9 +476,8 @@
  */
 #ifdef _IA16
 #undef DEBUG_ONLY_MEMBERS
+#undef _VERBOSE_STRUCTURES
 #define DEBUG_ONLY_MEMBERS(a)
-#undef OP_INFO_ENTRY
-#define OP_INFO_ENTRY(flags,name,Pargs,Iargs)     {flags,Pargs,Iargs}
 #endif
 
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acnamesp.h linux/drivers/acpi/include/acnamesp.h
--- v2.4.0/linux/drivers/acpi/include/acnamesp.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acnamesp.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acnamesp.h - Namespace subcomponent prototypes and defines
- *       $Revision: 100 $
+ *       $Revision: 101 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acobject.h linux/drivers/acpi/include/acobject.h
--- v2.4.0/linux/drivers/acpi/include/acobject.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acobject.h	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Name: acobject.h - Definition of ACPI_OPERAND_OBJECT  (Internal object only)
- *       $Revision: 75 $
+ *       $Revision: 78 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -113,10 +113,10 @@
 
 	ACPI_INTEGER                value;
 
-} ACPI_OBJECT_NUMBER;
+} ACPI_OBJECT_INTEGER;
 
 
-typedef struct /* STRING - has length and pointer */
+typedef struct /* STRING - has length and pointer - Null terminated, ASCII characters only */
 {
 	ACPI_OBJECT_COMMON_HEADER
 
@@ -126,13 +126,11 @@
 } ACPI_OBJECT_STRING;
 
 
-typedef struct /* BUFFER - has length, sequence, and pointer */
+typedef struct /* BUFFER - has length and pointer - not null terminated */
 {
 	ACPI_OBJECT_COMMON_HEADER
 
 	u32                         length;
-	u32                         sequence;       /* Sequential count of buffers created */
-
 	u8                          *pointer;       /* points to the buffer in allocated space */
 
 } ACPI_OBJECT_BUFFER;
@@ -398,7 +396,7 @@
 {
 	ACPI_OBJECT_COMMON          common;
 	ACPI_OBJECT_CACHE_LIST      cache;
-	ACPI_OBJECT_NUMBER          number;
+	ACPI_OBJECT_INTEGER         integer;
 	ACPI_OBJECT_STRING          string;
 	ACPI_OBJECT_BUFFER          buffer;
 	ACPI_OBJECT_PACKAGE         package;
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acoutput.h linux/drivers/acpi/include/acoutput.h
--- v2.4.0/linux/drivers/acpi/include/acoutput.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acoutput.h	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acoutput.h -- debug output
- *       $Revision: 66 $
+ *       $Revision: 69 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -58,6 +58,7 @@
 #define BATTERY                     0x00040000
 
 #define DEBUGGER                    0x00100000
+#define COMPILER                    0x00200000
 #define ALL_COMPONENTS              0x001FFFFF
 
 #define COMPONENT_DEFAULT           (ALL_COMPONENTS)
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acparser.h linux/drivers/acpi/include/acparser.h
--- v2.4.0/linux/drivers/acpi/include/acparser.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acparser.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: acparser.h - AML Parser subcomponent prototypes and defines
- *       $Revision: 47 $
+ *       $Revision: 49 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acpi.h linux/drivers/acpi/include/acpi.h
--- v2.4.0/linux/drivers/acpi/include/acpi.h	Fri Sep 15 14:30:30 2000
+++ linux/drivers/acpi/include/acpi.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acpi.h - Master include file, Publics and external data.
- *       $Revision: 48 $
+ *       $Revision: 50 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acpiosxf.h linux/drivers/acpi/include/acpiosxf.h
--- v2.4.0/linux/drivers/acpi/include/acpiosxf.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acpiosxf.h	Mon Jan 29 10:15:59 2001
@@ -9,7 +9,7 @@
 
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -121,6 +121,10 @@
 	void                    *logical_address,
 	u32                     length);
 
+ACPI_STATUS
+acpi_os_get_physical_address (
+	void                    *logical_address,
+	ACPI_PHYSICAL_ADDRESS   *physical_address);
 
 /*
  * Interrupt handlers
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acpixf.h linux/drivers/acpi/include/acpixf.h
--- v2.4.0/linux/drivers/acpi/include/acpixf.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/acpixf.h	Mon Jan 29 10:15:59 2001
@@ -6,7 +6,7 @@
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -283,6 +283,10 @@
 ACPI_STATUS
 acpi_get_firmware_waking_vector (
 	ACPI_PHYSICAL_ADDRESS   *physical_address);
+
+ACPI_STATUS
+acpi_enter_sleep_state (
+	u8 sleep_state);
 
 ACPI_STATUS
 acpi_get_processor_throttling_info (
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/acresrc.h linux/drivers/acpi/include/acresrc.h
--- v2.4.0/linux/drivers/acpi/include/acresrc.h	Fri Sep 15 14:30:30 2000
+++ linux/drivers/acpi/include/acresrc.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: acresrc.h - Resource Manager function prototypes
- *       $Revision: 20 $
+ *       $Revision: 22 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/actables.h linux/drivers/acpi/include/actables.h
--- v2.4.0/linux/drivers/acpi/include/actables.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/actables.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: actables.h - ACPI table management
- *       $Revision: 27 $
+ *       $Revision: 29 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/actbl.h linux/drivers/acpi/include/actbl.h
--- v2.4.0/linux/drivers/acpi/include/actbl.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/actbl.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: actbl.h - Table data structures defined in ACPI specification
- *       $Revision: 43 $
+ *       $Revision: 45 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/actbl1.h linux/drivers/acpi/include/actbl1.h
--- v2.4.0/linux/drivers/acpi/include/actbl1.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/actbl1.h	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: actbl1.h - ACPI 1.0 tables
- *       $Revision: 15 $
+ *       $Revision: 17 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/actbl2.h linux/drivers/acpi/include/actbl2.h
--- v2.4.0/linux/drivers/acpi/include/actbl2.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/actbl2.h	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: actbl2.h - ACPI Specification Revision 2.0 Tables
- *       $Revision: 19 $
+ *       $Revision: 21 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -142,8 +142,8 @@
 	u16                 plvl3_lat;         /* worst case HW latency to enter/exit C3 state */
 	u16                 flush_size;        /* number of flush strides that need to be read */
 	u16                 flush_stride;      /* Processor's memory cache line width, in bytes */
-	u8                  duty_offset;       /* Processor’s duty cycle index in processor's P_CNT reg*/
-	u8                  duty_width;        /* Processor’s duty cycle value bit width in P_CNT register.*/
+	u8                  duty_offset;       /* Processor_’s duty cycle index in processor's P_CNT reg*/
+	u8                  duty_width;        /* Processor_’s duty cycle value bit width in P_CNT register.*/
 	u8                  day_alrm;          /* index to day-of-month alarm in RTC CMOS RAM */
 	u8                  mon_alrm;          /* index to month-of-year alarm in RTC CMOS RAM */
 	u8                  century;           /* index to century in RTC CMOS RAM */
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/actbl71.h linux/drivers/acpi/include/actbl71.h
--- v2.4.0/linux/drivers/acpi/include/actbl71.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/actbl71.h	Mon Jan 22 13:23:42 2001
@@ -3,12 +3,12 @@
  * Name: actbl71.h - IA-64 Extensions to the ACPI Spec Rev. 0.71
  *                   This file includes tables specific to this
  *                   specification revision.
- *       $Revision: 7 $
+ *       $Revision: 9 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/actypes.h linux/drivers/acpi/include/actypes.h
--- v2.4.0/linux/drivers/acpi/include/actypes.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/actypes.h	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Name: actypes.h - Common data types for the entire ACPI subsystem
- *       $Revision: 159 $
+ *       $Revision: 163 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -97,7 +97,7 @@
 
 typedef UINT32                          ACPI_TBLPTR;
 typedef UINT32                          ACPI_IO_ADDRESS;
-typedef void                            *ACPI_PHYSICAL_ADDRESS;
+typedef char                            *ACPI_PHYSICAL_ADDRESS;
 
 #define ALIGNED_ADDRESS_BOUNDARY        0x00000002
 #define _HW_ALIGNMENT_SUPPORT
@@ -249,8 +249,9 @@
 #define ACPI_STATE_S2                   (u8) 2
 #define ACPI_STATE_S3                   (u8) 3
 #define ACPI_STATE_S4                   (u8) 4
-#define ACPI_STATE_S4_bIOS              (u8) 5
-#define ACPI_STATE_S5                   (u8) 6
+#define ACPI_STATE_S5                   (u8) 5
+/* let's pretend S4_bIOS didn't exist for now. ASG */
+#define ACPI_STATE_S4_bIOS              (u8) 6
 #define ACPI_S_STATES_MAX               ACPI_STATE_S5
 
 
@@ -284,8 +285,37 @@
 typedef u32                             ACPI_OBJECT_TYPE;
 typedef u8                              OBJECT_TYPE_INTERNAL;
 
+#define ACPI_BTYPE_ANY                  0x00000000
+#define ACPI_BTYPE_INTEGER               0x00000001
+#define ACPI_BTYPE_STRING               0x00000002
+#define ACPI_BTYPE_BUFFER               0x00000004
+#define ACPI_BTYPE_PACKAGE              0x00000008
+#define ACPI_BTYPE_FIELD_UNIT           0x00000010
+#define ACPI_BTYPE_DEVICE               0x00000020
+#define ACPI_BTYPE_EVENT                0x00000040
+#define ACPI_BTYPE_METHOD               0x00000080
+#define ACPI_BTYPE_MUTEX                0x00000100
+#define ACPI_BTYPE_REGION               0x00000200
+#define ACPI_BTYPE_POWER                0x00000400
+#define ACPI_BTYPE_PROCESSOR            0x00000800
+#define ACPI_BTYPE_THERMAL              0x00001000
+#define ACPI_BTYPE_BUFFER_FIELD         0x00002000
+#define ACPI_BTYPE_DDB_HANDLE           0x00004000
+#define ACPI_BTYPE_DEBUG_OBJECT         0x00008000
+#define ACPI_BTYPE_REFERENCE            0x00010000
+#define ACPI_BTYPE_RESOURCE             0x00020000
+
+#define ACPI_BTYPE_COMPUTE_DATA         (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER)
+
+#define ACPI_BTYPE_DATA                 (ACPI_BTYPE_COMPUTE_DATA  | ACPI_BTYPE_PACKAGE)
+#define ACPI_BTYPE_DATA_REFERENCE       (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE)
+#define ACPI_BTYPE_DEVICE_OBJECTS       (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR)
+#define ACPI_BTYPE_OBJECTS_AND_REFS     0x00017FFF  /* ARG or LOCAL */
+#define ACPI_BTYPE_ALL_OBJECTS          0x00007FFF
+
+
 #define ACPI_TYPE_ANY                   0  /* 0x00  */
-#define ACPI_TYPE_NUMBER                1  /* 0x01  Byte/Word/Dword/Zero/One/Ones */
+#define ACPI_TYPE_INTEGER               1  /* 0x01  Byte/Word/Dword/Zero/One/Ones */
 #define ACPI_TYPE_STRING                2  /* 0x02  */
 #define ACPI_TYPE_BUFFER                3  /* 0x03  */
 #define ACPI_TYPE_PACKAGE               4  /* 0x04  Byte_const, multiple Data_term/Constant/Super_name */
@@ -432,7 +462,7 @@
 	{
 		ACPI_OBJECT_TYPE            type;
 		ACPI_INTEGER                value;      /* The actual number */
-	} number;
+	} integer;
 
 	struct
 	{
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/include/amlcode.h linux/drivers/acpi/include/amlcode.h
--- v2.4.0/linux/drivers/acpi/include/amlcode.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/include/amlcode.h	Mon Jan 22 13:23:42 2001
@@ -3,12 +3,12 @@
  * Name: amlcode.h - Definitions for AML, as included in "definition blocks"
  *                   Declarations and definitions contained herein are derived
  *                   directly from the ACPI specification.
- *       $Revision: 42 $
+ *       $Revision: 46 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -211,27 +211,42 @@
 #define ARGP_TERMARG                0x0E
 #define ARGP_TERMLIST               0x0F
 #define ARGP_WORDDATA               0x10
+#define ARGP_QWORDDATA              0x11
+#define ARGP_SIMPLENAME             0x12
 
 /*
  * Resolved argument types for the AML Interpreter
  * Each field in the Arg_types u32 is 5 bits, allowing for a maximum of 6 arguments.
- * There can be up to 31 unique argument types
+ * There can be up to 31 unique argument types (0 is end-of-arg-list indicator)
  */
 
-#define ARGI_ANYTYPE                0x01
-#define ARGI_TARGETREF              0x02
-#define ARGI_REFERENCE              0x03
-#define ARGI_IF                     0x04
-#define ARGI_NUMBER                 0x05
-#define ARGI_STRING                 0x06
-#define ARGI_BUFFER                 0x07
-#define ARGI_PACKAGE                0x08
-#define ARGI_DATAOBJECT             0x09     /* Buffer, string, package or reference to a Node - Used only by Size_of operator*/
-#define ARGI_COMPLEXOBJ             0x0A     /* Buffer or package */
-#define ARGI_MUTEX                  0x0B
-#define ARGI_EVENT                  0x0C
-#define ARGI_REGION                 0x0D
-#define ARGI_DDBHANDLE              0x0E
+/* "Standard" ACPI types are 1-15 (0x0F) */
+
+#define ARGI_INTEGER                 ACPI_TYPE_INTEGER        /* 1 */
+#define ARGI_STRING                 ACPI_TYPE_STRING        /* 2 */
+#define ARGI_BUFFER                 ACPI_TYPE_BUFFER        /* 3 */
+#define ARGI_PACKAGE                ACPI_TYPE_PACKAGE       /* 4 */
+#define ARGI_EVENT                  ACPI_TYPE_EVENT
+#define ARGI_MUTEX                  ACPI_TYPE_MUTEX
+#define ARGI_REGION                 ACPI_TYPE_REGION
+#define ARGI_DDBHANDLE              ACPI_TYPE_DDB_HANDLE
+
+/* Custom types are 0x10 through 0x1F */
+
+#define ARGI_IF                     0x10
+#define ARGI_ANYOBJECT              0x11
+#define ARGI_ANYTYPE                0x12
+#define ARGI_COMPUTEDATA            0x13     /* Buffer, String, or Integer */
+#define ARGI_DATAOBJECT             0x14     /* Buffer, string, package or reference to a Node - Used only by Size_of operator*/
+#define ARGI_COMPLEXOBJ             0x15     /* Buffer or package */
+#define ARGI_INTEGER_REF            0x16
+#define ARGI_OBJECT_REF             0x17
+#define ARGI_DEVICE_REF             0x18
+#define ARGI_REFERENCE              0x19
+#define ARGI_TARGETREF              0x1A     /* Target, subject to implicit conversion */
+#define ARGI_FIXED_TARGET           0x1B     /* Target, no implicit conversion */
+#define ARGI_SIMPLE_TARGET          0x1C     /* Name, Local, Arg -- no implicit conversion */
+#define ARGI_BUFFERSTRING           0x1D
 
 #define ARGI_INVALID_OPCODE         0xFFFFFFFF
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amconfig.c linux/drivers/acpi/interpreter/amconfig.c
--- v2.4.0/linux/drivers/acpi/interpreter/amconfig.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amconfig.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: amconfig - Namespace reconfiguration (Load/Unload opcodes)
- *              $Revision: 26 $
+ *              $Revision: 29 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -73,7 +73,8 @@
 	table_header.length = 0;
 	for (i = 0; i < sizeof (ACPI_TABLE_HEADER); i++) {
 		status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ,
-				  i, 8, (u32 *) ((u8 *) &table_header + i));
+				   (ACPI_PHYSICAL_ADDRESS) i, 8,
+				   (u32 *) ((u8 *) &table_header + i));
 		if (ACPI_FAILURE (status)) {
 			return (status);
 		}
@@ -96,7 +97,8 @@
 
 	for (i = 0; i < table_header.length; i++) {
 		status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ,
-				  i, 8, (u32 *) (table_data_ptr + i));
+				   (ACPI_PHYSICAL_ADDRESS)i, 8,
+				   (u32 *) (table_data_ptr + i));
 		if (ACPI_FAILURE (status)) {
 			goto cleanup;
 		}
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amconvrt.c linux/drivers/acpi/interpreter/amconvrt.c
--- v2.4.0/linux/drivers/acpi/interpreter/amconvrt.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/interpreter/amconvrt.c	Mon Jan 29 10:15:59 2001
@@ -0,0 +1,525 @@
+/******************************************************************************
+ *
+ * Module Name: amconvrt - Object conversion routines
+ *              $Revision: 3 $
+ *
+ *****************************************************************************/
+
+/*
+ *  Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "acpi.h"
+#include "acparser.h"
+#include "acnamesp.h"
+#include "acinterp.h"
+#include "acevents.h"
+#include "amlcode.h"
+#include "acdispat.h"
+
+
+#define _COMPONENT          INTERPRETER
+	 MODULE_NAME         ("amconvrt")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_convert_to_target_type
+ *
+ * PARAMETERS:  *Obj_desc       - Object to be converted.
+ *              Walk_state      - Current method state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_target_type (
+	OBJECT_TYPE_INTERNAL    destination_type,
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_STATUS             status = AE_OK;
+
+
+	/*
+	 * If required by the target,
+	 * perform implicit conversion on the source before we store it.
+	 */
+
+	switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args))
+	{
+	case ARGI_SIMPLE_TARGET:
+	case ARGI_FIXED_TARGET:
+	case ARGI_INTEGER_REF:      /* Handles Increment, Decrement cases */
+
+		switch (destination_type)
+		{
+		case INTERNAL_TYPE_DEF_FIELD:
+			/*
+			 * Named field can always handle conversions
+			 */
+			break;
+
+		default:
+			/* No conversion allowed for these types */
+
+			if (destination_type != (*obj_desc)->common.type) {
+				status = AE_TYPE;
+			}
+		}
+		break;
+
+
+	case ARGI_TARGETREF:
+
+		switch (destination_type)
+		{
+		case ACPI_TYPE_INTEGER:
+		case ACPI_TYPE_FIELD_UNIT:
+		case INTERNAL_TYPE_BANK_FIELD:
+		case INTERNAL_TYPE_INDEX_FIELD:
+			/*
+			 * These types require an Integer operand.  We can convert
+			 * a Buffer or a String to an Integer if necessary.
+			 */
+			status = acpi_aml_convert_to_integer (obj_desc, walk_state);
+			break;
+
+
+		case ACPI_TYPE_STRING:
+
+			/*
+			 * The operand must be a String.  We can convert an
+			 * Integer or Buffer if necessary
+			 */
+			status = acpi_aml_convert_to_string (obj_desc, walk_state);
+			break;
+
+
+		case ACPI_TYPE_BUFFER:
+
+			/*
+			 * The operand must be a String.  We can convert an
+			 * Integer or Buffer if necessary
+			 */
+			status = acpi_aml_convert_to_buffer (obj_desc, walk_state);
+			break;
+		}
+		break;
+
+
+	case ARGI_REFERENCE:
+		/*
+		 * Create_xxxx_field cases - we are storing the field object into the name
+		 */
+		break;
+
+
+	default:
+		status = AE_AML_INTERNAL;
+	}
+
+
+	/*
+	 * Source-to-Target conversion semantics:
+	 *
+	 * If conversion to the target type cannot be performed, then simply
+	 * overwrite the target with the new object and type.
+	 */
+	if (status == AE_TYPE) {
+		status = AE_OK;
+	}
+
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_convert_to_integer
+ *
+ * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
+ *                                Integer, Buffer, or String
+ *              Walk_state      - Current method state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Convert an ACPI Object to an integer.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_integer (
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	u32                     i;
+	ACPI_OPERAND_OBJECT     *ret_desc;
+	u32                     count;
+	char                    *pointer;
+	ACPI_INTEGER            result;
+	u32                     integer_size = sizeof (ACPI_INTEGER);
+
+
+	switch ((*obj_desc)->common.type)
+	{
+	case ACPI_TYPE_INTEGER:
+		return (AE_OK);
+
+	case ACPI_TYPE_STRING:
+		pointer = (*obj_desc)->string.pointer;
+		count = (*obj_desc)->string.length;
+		break;
+
+	case ACPI_TYPE_BUFFER:
+		pointer = (char *) (*obj_desc)->buffer.pointer;
+		count = (*obj_desc)->buffer.length;
+		break;
+
+	default:
+		return (AE_TYPE);
+	}
+
+	/*
+	 * Create a new integer
+	 */
+	ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
+	if (!ret_desc) {
+		return (AE_NO_MEMORY);
+	}
+
+
+	/* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+	if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+		/*
+		 * We are running a method that exists in a 32-bit ACPI table.
+		 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
+		 */
+		integer_size = sizeof (u32);
+	}
+
+
+	/*
+	 * Convert the buffer/string to an integer.  Note that both buffers and
+	 * strings are treated as raw data - we don't convert ascii to hex for
+	 * strings.
+	 *
+	 * There are two terminating conditions for the loop:
+	 * 1) The size of an integer has been reached, or
+	 * 2) The end of the buffer or string has been reached
+	 */
+	result = 0;
+
+	/* Transfer no more than an integer's worth of data */
+
+	if (count > integer_size) {
+		count = integer_size;
+	}
+
+	/*
+	 * String conversion is different than Buffer conversion
+	 */
+	switch ((*obj_desc)->common.type)
+	{
+	case ACPI_TYPE_STRING:
+
+		/* TBD: Need to use 64-bit STRTOUL */
+
+		/*
+		 * Convert string to an integer
+		 * String must be hexadecimal as per the ACPI specification
+		 */
+
+		result = STRTOUL (pointer, NULL, 16);
+		break;
+
+
+	case ACPI_TYPE_BUFFER:
+
+		/*
+		 * Buffer conversion - we simply grab enough raw data from the
+		 * buffer to fill an integer
+		 */
+		for (i = 0; i < count; i++) {
+			/*
+			 * Get next byte and shift it into the Result.
+			 * Little endian is used, meaning that the first byte of the buffer
+			 * is the LSB of the integer
+			 */
+			result |= (((ACPI_INTEGER) pointer[i]) << (i * 8));
+		}
+
+		break;
+	}
+
+	/* Save the Result, delete original descriptor, store new descriptor */
+
+	ret_desc->integer.value = result;
+
+	if (walk_state->opcode != AML_STORE_OP) {
+		acpi_cm_remove_reference (*obj_desc);
+	}
+
+	*obj_desc = ret_desc;
+
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_convert_to_buffer
+ *
+ * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
+ *                                Integer, Buffer, or String
+ *              Walk_state      - Current method state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Convert an ACPI Object to an Buffer
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_buffer (
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_OPERAND_OBJECT     *ret_desc;
+	u32                     i;
+	u32                     integer_size = sizeof (ACPI_INTEGER);
+	u8                      *new_buf;
+
+
+	switch ((*obj_desc)->common.type)
+	{
+	case ACPI_TYPE_INTEGER:
+
+		/*
+		 * Create a new Buffer
+		 */
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
+		if (!ret_desc) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+		if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+			/*
+			 * We are running a method that exists in a 32-bit ACPI table.
+			 * Truncate the value to 32 bits by zeroing out the upper
+			 * 32-bit field
+			 */
+			integer_size = sizeof (u32);
+		}
+
+		/* Need enough space for one integers */
+
+		ret_desc->buffer.length = integer_size;
+		new_buf = acpi_cm_callocate (integer_size);
+		if (!new_buf) {
+			REPORT_ERROR
+				(("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+			acpi_cm_remove_reference (ret_desc);
+			return (AE_NO_MEMORY);
+		}
+
+		/* Copy the integer to the buffer */
+
+		for (i = 0; i < integer_size; i++) {
+			new_buf[i] = (u8) ((*obj_desc)->integer.value >> (i * 8));
+		}
+		ret_desc->buffer.pointer = new_buf;
+
+		/* Return the new buffer descriptor */
+
+		if (walk_state->opcode != AML_STORE_OP) {
+			acpi_cm_remove_reference (*obj_desc);
+		}
+		*obj_desc = ret_desc;
+		break;
+
+
+	case ACPI_TYPE_STRING:
+		break;
+
+
+	case ACPI_TYPE_BUFFER:
+		break;
+
+
+	default:
+		return (AE_TYPE);
+		break;
+   }
+
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_convert_to_string
+ *
+ * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
+ *                                Integer, Buffer, or String
+ *              Walk_state      - Current method state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Convert an ACPI Object to a string
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_string (
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_OPERAND_OBJECT     *ret_desc;
+	u32                     i;
+	u32                     index;
+	u32                     integer_size = sizeof (ACPI_INTEGER);
+	u8                      *new_buf;
+	u8                      *pointer;
+
+
+	switch ((*obj_desc)->common.type)
+	{
+	case ACPI_TYPE_INTEGER:
+
+		/*
+		 * Create a new String
+		 */
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
+		if (!ret_desc) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+		if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+			/*
+			 * We are running a method that exists in a 32-bit ACPI table.
+			 * Truncate the value to 32 bits by zeroing out the upper
+			 * 32-bit field
+			 */
+			integer_size = sizeof (u32);
+		}
+
+		/* Need enough space for one ASCII integer plus null terminator */
+
+		ret_desc->string.length = (integer_size * 2) + 1;
+		new_buf = acpi_cm_callocate (ret_desc->string.length);
+		if (!new_buf) {
+			REPORT_ERROR
+				(("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+			acpi_cm_remove_reference (ret_desc);
+			return (AE_NO_MEMORY);
+		}
+
+		/* Copy the integer to the buffer */
+
+		for (i = 0; i < (integer_size * 2); i++) {
+			new_buf[i] = acpi_gbl_hex_to_ascii [((*obj_desc)->integer.value >> (i * 4)) & 0xF];
+		}
+
+		/* Null terminate */
+
+		new_buf [i] = 0;
+		ret_desc->buffer.pointer = new_buf;
+
+		/* Return the new buffer descriptor */
+
+		if (walk_state->opcode != AML_STORE_OP) {
+			acpi_cm_remove_reference (*obj_desc);
+		}
+		*obj_desc = ret_desc;
+
+		return (AE_OK);
+
+
+	case ACPI_TYPE_BUFFER:
+
+		if (((*obj_desc)->buffer.length * 3) > ACPI_MAX_STRING_CONVERSION) {
+			return (AE_AML_STRING_LIMIT);
+		}
+
+		/*
+		 * Create a new String
+		 */
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
+		if (!ret_desc) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Need enough space for one ASCII integer plus null terminator */
+
+		ret_desc->string.length = (*obj_desc)->buffer.length * 3;
+		new_buf = acpi_cm_callocate (ret_desc->string.length + 1);
+		if (!new_buf) {
+			REPORT_ERROR
+				(("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+			acpi_cm_remove_reference (ret_desc);
+			return (AE_NO_MEMORY);
+		}
+
+		/*
+		 * Convert each byte of the buffer to two ASCII characters plus a space.
+		 */
+		pointer = (*obj_desc)->buffer.pointer;
+		index = 0;
+		for (i = 0; i < (*obj_desc)->buffer.length; i++) {
+			new_buf[index + 0] = acpi_gbl_hex_to_ascii [pointer[i] & 0x0F];
+			new_buf[index + 1] = acpi_gbl_hex_to_ascii [(pointer[i] >> 4) & 0x0F];
+			new_buf[index + 2] = ' ';
+			index += 3;
+		}
+
+		/* Null terminate */
+
+		new_buf [index] = 0;
+		ret_desc->buffer.pointer = new_buf;
+
+		/* Return the new buffer descriptor */
+
+		if (walk_state->opcode != AML_STORE_OP) {
+			acpi_cm_remove_reference (*obj_desc);
+		}
+		*obj_desc = ret_desc;
+		break;
+
+
+	case ACPI_TYPE_STRING:
+		break;
+
+
+	default:
+		return (AE_TYPE);
+		break;
+   }
+
+	return (AE_OK);
+}
+
+
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amcreate.c linux/drivers/acpi/interpreter/amcreate.c
--- v2.4.0/linux/drivers/acpi/interpreter/amcreate.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amcreate.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: amcreate - Named object creation
- *              $Revision: 51 $
+ *              $Revision: 53 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -353,7 +353,7 @@
 		goto cleanup;
 	}
 
-	obj_desc->mutex.sync_level = (u8) sync_desc->number.value;
+	obj_desc->mutex.sync_level = (u8) sync_desc->integer.value;
 
 	/* Obj_desc was on the stack top, and the name is below it */
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amdyadic.c linux/drivers/acpi/interpreter/amdyadic.c
--- v2.4.0/linux/drivers/acpi/interpreter/amdyadic.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amdyadic.c	Mon Jan 22 13:23:42 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: amdyadic - ACPI AML (p-code) execution for dyadic operators
- *              $Revision: 68 $
+ *              $Revision: 71 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -37,7 +37,174 @@
 	 MODULE_NAME         ("amdyadic")
 
 
-/*****************************************************************************
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_do_concatenate
+ *
+ * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
+ *                                Integer, Buffer, or String
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_do_concatenate (
+	ACPI_OPERAND_OBJECT     *obj_desc,
+	ACPI_OPERAND_OBJECT     *obj_desc2,
+	ACPI_OPERAND_OBJECT     **actual_ret_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_STATUS             status;
+	u32                     i;
+	ACPI_INTEGER            this_integer;
+	ACPI_OPERAND_OBJECT     *ret_desc;
+	NATIVE_CHAR             *new_buf;
+	u32                     integer_size = sizeof (ACPI_INTEGER);
+
+
+	/*
+	 * There are three cases to handle:
+	 * 1) Two Integers concatenated to produce a buffer
+	 * 2) Two Strings concatenated to produce a string
+	 * 3) Two Buffers concatenated to produce a buffer
+	 */
+	switch (obj_desc->common.type)
+	{
+	case ACPI_TYPE_INTEGER:
+
+		/* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+		if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+			/*
+			 * We are running a method that exists in a 32-bit ACPI table.
+			 * Truncate the value to 32 bits by zeroing out the upper
+			 * 32-bit field
+			 */
+			integer_size = sizeof (u32);
+		}
+
+		/* Result of two integers is a buffer */
+
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
+		if (!ret_desc) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Need enough space for two integers */
+
+		ret_desc->buffer.length = integer_size * 2;
+		new_buf = acpi_cm_callocate (ret_desc->buffer.length);
+		if (!new_buf) {
+			REPORT_ERROR
+				(("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+			status = AE_NO_MEMORY;
+			goto cleanup;
+		}
+
+		ret_desc->buffer.pointer = (u8 *) new_buf;
+
+		/* Convert the first integer */
+
+		this_integer = obj_desc->integer.value;
+		for (i = 0; i < integer_size; i++) {
+			new_buf[i] = (u8) this_integer;
+			this_integer >>= 8;
+		}
+
+		/* Convert the second integer */
+
+		this_integer = obj_desc2->integer.value;
+		for (; i < (integer_size * 2); i++) {
+			new_buf[i] = (u8) this_integer;
+			this_integer >>= 8;
+		}
+
+		break;
+
+
+	case ACPI_TYPE_STRING:
+
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
+		if (!ret_desc) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Operand1 is string  */
+
+		new_buf = acpi_cm_allocate (obj_desc->string.length +
+				  obj_desc2->string.length + 1);
+		if (!new_buf) {
+			REPORT_ERROR
+				(("Aml_exec_dyadic2_r/Concat_op: String allocation failure\n"));
+			status = AE_NO_MEMORY;
+			goto cleanup;
+		}
+
+		STRCPY (new_buf, obj_desc->string.pointer);
+		STRCPY (new_buf + obj_desc->string.length,
+				  obj_desc2->string.pointer);
+
+		/* Point the return object to the new string */
+
+		ret_desc->string.pointer = new_buf;
+		ret_desc->string.length = obj_desc->string.length +=
+				  obj_desc2->string.length;
+		break;
+
+
+	case ACPI_TYPE_BUFFER:
+
+		/* Operand1 is a buffer */
+
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
+		if (!ret_desc) {
+			return (AE_NO_MEMORY);
+		}
+
+		new_buf = acpi_cm_allocate (obj_desc->buffer.length +
+				  obj_desc2->buffer.length);
+		if (!new_buf) {
+			REPORT_ERROR
+				(("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+			status = AE_NO_MEMORY;
+			goto cleanup;
+		}
+
+		MEMCPY (new_buf, obj_desc->buffer.pointer,
+				  obj_desc->buffer.length);
+		MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer,
+				  obj_desc2->buffer.length);
+
+		/*
+		 * Point the return object to the new buffer
+		 */
+
+		ret_desc->buffer.pointer    = (u8 *) new_buf;
+		ret_desc->buffer.length     = obj_desc->buffer.length +
+				 obj_desc2->buffer.length;
+		break;
+
+	default:
+		status = AE_AML_INTERNAL;
+		ret_desc = NULL;
+	}
+
+
+	*actual_ret_desc = ret_desc;
+	return (AE_OK);
+
+
+cleanup:
+
+	acpi_cm_remove_reference (ret_desc);
+	return (status);
+}
+
+
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_aml_exec_dyadic1
  *
@@ -50,7 +217,7 @@
  *
  * ALLOCATION:  Deletes both operands
  *
- ****************************************************************************/
+ ******************************************************************************/
 
 ACPI_STATUS
 acpi_aml_exec_dyadic1 (
@@ -106,7 +273,7 @@
 
 				/* Dispatch the notify to the appropriate handler */
 
-				acpi_ev_notify_dispatch (node, (u32) val_desc->number.value);
+				acpi_ev_notify_dispatch (node, (u32) val_desc->integer.value);
 				break;
 
 			default:
@@ -135,7 +302,7 @@
 }
 
 
-/*****************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_aml_exec_dyadic2_r
  *
@@ -148,7 +315,7 @@
  *
  * ALLOCATION:  Deletes one operand descriptor -- other remains on stack
  *
- ****************************************************************************/
+ ******************************************************************************/
 
 ACPI_STATUS
 acpi_aml_exec_dyadic2_r (
@@ -164,7 +331,6 @@
 	ACPI_OPERAND_OBJECT     *ret_desc2  = NULL;
 	ACPI_STATUS             status      = AE_OK;
 	u32                     num_operands = 3;
-	NATIVE_CHAR             *new_buf;
 
 
 	/* Resolve all operands */
@@ -201,7 +367,7 @@
 	case AML_SHIFT_RIGHT_OP:
 	case AML_SUBTRACT_OP:
 
-		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 		if (!ret_desc) {
 			status = AE_NO_MEMORY;
 			goto cleanup;
@@ -222,8 +388,8 @@
 
 	case AML_ADD_OP:
 
-		ret_desc->number.value = obj_desc->number.value +
-				 obj_desc2->number.value;
+		ret_desc->integer.value = obj_desc->integer.value +
+				 obj_desc2->integer.value;
 		break;
 
 
@@ -231,8 +397,8 @@
 
 	case AML_BIT_AND_OP:
 
-		ret_desc->number.value = obj_desc->number.value &
-				 obj_desc2->number.value;
+		ret_desc->integer.value = obj_desc->integer.value &
+				 obj_desc2->integer.value;
 		break;
 
 
@@ -240,8 +406,8 @@
 
 	case AML_BIT_NAND_OP:
 
-		ret_desc->number.value = ~(obj_desc->number.value &
-				   obj_desc2->number.value);
+		ret_desc->integer.value = ~(obj_desc->integer.value &
+				   obj_desc2->integer.value);
 		break;
 
 
@@ -249,8 +415,8 @@
 
 	case AML_BIT_OR_OP:
 
-		ret_desc->number.value = obj_desc->number.value |
-				 obj_desc2->number.value;
+		ret_desc->integer.value = obj_desc->integer.value |
+				 obj_desc2->integer.value;
 		break;
 
 
@@ -258,8 +424,8 @@
 
 	case AML_BIT_NOR_OP:
 
-		ret_desc->number.value = ~(obj_desc->number.value |
-				   obj_desc2->number.value);
+		ret_desc->integer.value = ~(obj_desc->integer.value |
+				   obj_desc2->integer.value);
 		break;
 
 
@@ -267,16 +433,16 @@
 
 	case AML_BIT_XOR_OP:
 
-		ret_desc->number.value = obj_desc->number.value ^
-				 obj_desc2->number.value;
+		ret_desc->integer.value = obj_desc->integer.value ^
+				 obj_desc2->integer.value;
 		break;
 
 
-	/* Def_divide  :=  Divide_op Dividend Divisor Remainder Quotient   */
+	/* Def_divide  :=  Divide_op Dividend Divisor Remainder Quotient */
 
 	case AML_DIVIDE_OP:
 
-		if (!obj_desc2->number.value) {
+		if (!obj_desc2->integer.value) {
 			REPORT_ERROR
 				(("Aml_exec_dyadic2_r/Divide_op: Divide by zero\n"));
 
@@ -284,7 +450,7 @@
 			goto cleanup;
 		}
 
-		ret_desc2 = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+		ret_desc2 = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 		if (!ret_desc2) {
 			status = AE_NO_MEMORY;
 			goto cleanup;
@@ -292,13 +458,13 @@
 
 		/* Remainder (modulo) */
 
-		ret_desc->number.value  = ACPI_MODULO (obj_desc->number.value,
-				  obj_desc2->number.value);
+		ret_desc->integer.value  = ACPI_MODULO (obj_desc->integer.value,
+				  obj_desc2->integer.value);
 
 		/* Result (what we used to call the quotient) */
 
-		ret_desc2->number.value = ACPI_DIVIDE (obj_desc->number.value,
-				  obj_desc2->number.value);
+		ret_desc2->integer.value = ACPI_DIVIDE (obj_desc->integer.value,
+				  obj_desc2->integer.value);
 		break;
 
 
@@ -306,8 +472,8 @@
 
 	case AML_MULTIPLY_OP:
 
-		ret_desc->number.value = obj_desc->number.value *
-				 obj_desc2->number.value;
+		ret_desc->integer.value = obj_desc->integer.value *
+				 obj_desc2->integer.value;
 		break;
 
 
@@ -315,8 +481,8 @@
 
 	case AML_SHIFT_LEFT_OP:
 
-		ret_desc->number.value = obj_desc->number.value <<
-				 obj_desc2->number.value;
+		ret_desc->integer.value = obj_desc->integer.value <<
+				 obj_desc2->integer.value;
 		break;
 
 
@@ -324,8 +490,8 @@
 
 	case AML_SHIFT_RIGHT_OP:
 
-		ret_desc->number.value = obj_desc->number.value >>
-				 obj_desc2->number.value;
+		ret_desc->integer.value = obj_desc->integer.value >>
+				 obj_desc2->integer.value;
 		break;
 
 
@@ -333,8 +499,8 @@
 
 	case AML_SUBTRACT_OP:
 
-		ret_desc->number.value = obj_desc->number.value -
-				 obj_desc2->number.value;
+		ret_desc->integer.value = obj_desc->integer.value -
+				 obj_desc2->integer.value;
 		break;
 
 
@@ -342,79 +508,54 @@
 
 	case AML_CONCAT_OP:
 
-		if (obj_desc2->common.type != obj_desc->common.type) {
-			status = AE_AML_OPERAND_TYPE;
-			goto cleanup;
-		}
-
-		/* Both operands are now known to be the same */
-
-		if (ACPI_TYPE_STRING == obj_desc->common.type) {
-			ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
-			if (!ret_desc) {
-				status = AE_NO_MEMORY;
-				goto cleanup;
-			}
-
-			/* Operand1 is string  */
 
-			new_buf = acpi_cm_allocate (obj_desc->string.length +
-					  obj_desc2->string.length + 1);
-			if (!new_buf) {
-				REPORT_ERROR
-					(("Aml_exec_dyadic2_r/Concat_op: String allocation failure\n"));
-				status = AE_NO_MEMORY;
-				goto cleanup;
-			}
-
-			STRCPY (new_buf, obj_desc->string.pointer);
-			STRCPY (new_buf + obj_desc->string.length,
-					  obj_desc2->string.pointer);
+		/*
+		 * Convert the second operand if necessary.  The first operand
+		 * determines the type of the second operand, (See the Data Types
+		 * section of the ACPI specification.)  Both object types are
+		 * guaranteed to be either Integer/String/Buffer by the operand
+		 * resolution mechanism above.
+		 */
 
-			/* Point the return object to the new string */
+		switch (obj_desc->common.type)
+		{
+		case ACPI_TYPE_INTEGER:
+			status = acpi_aml_convert_to_integer (&obj_desc2, walk_state);
+			break;
+
+		case ACPI_TYPE_STRING:
+			status = acpi_aml_convert_to_string (&obj_desc2, walk_state);
+			break;
+
+		case ACPI_TYPE_BUFFER:
+			status = acpi_aml_convert_to_buffer (&obj_desc2, walk_state);
+			break;
 
-			ret_desc->string.pointer = new_buf;
-			ret_desc->string.length = obj_desc->string.length +=
-					  obj_desc2->string.length;
+		default:
+			status = AE_AML_INTERNAL;
 		}
 
-		else {
-			/* Operand1 is not a string ==> must be a buffer */
-
-			ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
-			if (!ret_desc) {
-				status = AE_NO_MEMORY;
-				goto cleanup;
-			}
-
-			new_buf = acpi_cm_allocate (obj_desc->buffer.length +
-					  obj_desc2->buffer.length);
-			if (!new_buf) {
-				REPORT_ERROR
-					(("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
-				status = AE_NO_MEMORY;
-				goto cleanup;
-			}
-
-			MEMCPY (new_buf, obj_desc->buffer.pointer,
-					  obj_desc->buffer.length);
-			MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer,
-					  obj_desc2->buffer.length);
+		if (ACPI_FAILURE (status)) {
+			goto cleanup;
+		}
 
-			/*
-			 * Point the return object to the new buffer
-			 */
 
-			ret_desc->buffer.pointer    = (u8 *) new_buf;
-			ret_desc->buffer.length     = obj_desc->buffer.length +
-					 obj_desc2->buffer.length;
+		/*
+		 * Both operands are now known to be the same object type
+		 * (Both are Integer, String, or Buffer), and we can now perform the
+		 * concatenation.
+		 */
+		status = acpi_aml_do_concatenate (obj_desc, obj_desc2, &ret_desc, walk_state);
+		if (ACPI_FAILURE (status)) {
+			goto cleanup;
 		}
 		break;
 
 
 	default:
 
-		REPORT_ERROR (("Acpi_aml_exec_dyadic2_r: Unknown dyadic opcode %X\n", opcode));
+		REPORT_ERROR (("Acpi_aml_exec_dyadic2_r: Unknown dyadic opcode %X\n",
+				opcode));
 		status = AE_AML_BAD_OPCODE;
 		goto cleanup;
 	}
@@ -474,7 +615,7 @@
 }
 
 
-/*****************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_aml_exec_dyadic2_s
  *
@@ -486,7 +627,7 @@
  *
  * ALLOCATION:  Deletes one operand descriptor -- other remains on stack
  *
- ****************************************************************************/
+ ******************************************************************************/
 
 ACPI_STATUS
 acpi_aml_exec_dyadic2_s (
@@ -516,7 +657,7 @@
 
 	/* Create the internal return object */
 
-	ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+	ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 	if (!ret_desc) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
@@ -524,7 +665,7 @@
 
 	/* Default return value is FALSE, operation did not time out */
 
-	ret_desc->number.value = 0;
+	ret_desc->integer.value = 0;
 
 
 	/* Examine the opcode */
@@ -562,7 +703,7 @@
 	 */
 
 	if (status == AE_TIME) {
-		ret_desc->number.value = ACPI_INTEGER_MAX;  /* TRUE, op timed out */
+		ret_desc->integer.value = ACPI_INTEGER_MAX;  /* TRUE, op timed out */
 		status = AE_OK;
 	}
 
@@ -591,7 +732,7 @@
 }
 
 
-/*****************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_aml_exec_dyadic2
  *
@@ -605,7 +746,7 @@
  * ALLOCATION:  Deletes one operand descriptor -- other remains on stack
  *              containing result value
  *
- ****************************************************************************/
+ ******************************************************************************/
 
 ACPI_STATUS
 acpi_aml_exec_dyadic2 (
@@ -636,7 +777,7 @@
 
 	/* Create the internal return object */
 
-	ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+	ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 	if (!ret_desc) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
@@ -654,8 +795,8 @@
 
 	case AML_LAND_OP:
 
-		lboolean = (u8) (obj_desc->number.value &&
-				  obj_desc2->number.value);
+		lboolean = (u8) (obj_desc->integer.value &&
+				  obj_desc2->integer.value);
 		break;
 
 
@@ -663,8 +804,8 @@
 
 	case AML_LEQUAL_OP:
 
-		lboolean = (u8) (obj_desc->number.value ==
-				  obj_desc2->number.value);
+		lboolean = (u8) (obj_desc->integer.value ==
+				  obj_desc2->integer.value);
 		break;
 
 
@@ -672,8 +813,8 @@
 
 	case AML_LGREATER_OP:
 
-		lboolean = (u8) (obj_desc->number.value >
-				  obj_desc2->number.value);
+		lboolean = (u8) (obj_desc->integer.value >
+				  obj_desc2->integer.value);
 		break;
 
 
@@ -681,8 +822,8 @@
 
 	case AML_LLESS_OP:
 
-		lboolean = (u8) (obj_desc->number.value <
-				  obj_desc2->number.value);
+		lboolean = (u8) (obj_desc->integer.value <
+				  obj_desc2->integer.value);
 		break;
 
 
@@ -690,8 +831,8 @@
 
 	case AML_LOR_OP:
 
-		lboolean = (u8) (obj_desc->number.value ||
-				  obj_desc2->number.value);
+		lboolean = (u8) (obj_desc->integer.value ||
+				  obj_desc2->integer.value);
 		break;
 
 
@@ -707,10 +848,10 @@
 	/* Set return value to logical TRUE (all ones) or FALSE (zero) */
 
 	if (lboolean) {
-		ret_desc->number.value = ACPI_INTEGER_MAX;
+		ret_desc->integer.value = ACPI_INTEGER_MAX;
 	}
 	else {
-		ret_desc->number.value = 0;
+		ret_desc->integer.value = 0;
 	}
 
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amfield.c linux/drivers/acpi/interpreter/amfield.c
--- v2.4.0/linux/drivers/acpi/interpreter/amfield.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amfield.c	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: amfield - ACPI AML (p-code) execution - field manipulation
- *              $Revision: 74 $
+ *              $Revision: 77 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -174,7 +174,8 @@
 	u32                     byte_field_length;
 
 
-	/* Basic data checking */
+	/* Parameter validation */
+
 	if ((!named_field) || (ACPI_READ == mode && !buffer)) {
 		return (AE_AML_INTERNAL);
 	}
@@ -227,7 +228,7 @@
 
 	/* TBD: should these round down to a power of 2? */
 
-	if (DIV_8(bit_granularity) > byte_field_length) {
+	if (DIV_8 (bit_granularity) > byte_field_length) {
 		bit_granularity = MUL_8(byte_field_length);
 	}
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amfldio.c linux/drivers/acpi/interpreter/amfldio.c
--- v2.4.0/linux/drivers/acpi/interpreter/amfldio.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amfldio.c	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: amfldio - Aml Field I/O
- *              $Revision: 32 $
+ *              $Revision: 37 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -132,7 +132,7 @@
 	u32                     this_field_byte_offset;
 	u32                     this_field_datum_offset;
 	u32                     previous_raw_datum;
-	u32                     this_raw_datum;
+	u32                     this_raw_datum = 0;
 	u32                     valid_field_bits;
 	u32                     mask;
 	u32                     merged_datum = 0;
@@ -203,32 +203,46 @@
 
 		while (this_field_datum_offset < datum_length) {
 			/*
-			 * Get the next raw datum, it contains bits of the current
-			 * field datum
+			 * If the field is aligned on a byte boundary, we don't want
+			 * to perform a final read, since this would potentially read
+			 * past the end of the region.
+			 *
+			 * TBD: [Investigate] It may make more sense to just split the aligned
+			 * and non-aligned cases since the aligned case is so very simple,
 			 */
-
-			status = acpi_aml_read_field_data (obj_desc,
-					  this_field_byte_offset + byte_granularity,
-					  bit_granularity, &this_raw_datum);
-			if (ACPI_FAILURE (status)) {
-				goto cleanup;
-			}
-
-			/* Before merging the data, make sure the unused bits are clear */
-
-			switch (byte_granularity)
+			if ((obj_desc->field.bit_offset != 0) ||
+				((obj_desc->field.bit_offset == 0) &&
+				(this_field_datum_offset < (datum_length -1))))
 			{
-			case 1:
-				this_raw_datum &= 0x000000FF;
-				previous_raw_datum &= 0x000000FF;
-				break;
-
-			case 2:
-				this_raw_datum &= 0x0000FFFF;
-				previous_raw_datum &= 0x0000FFFF;
-				break;
+				/*
+				 * Get the next raw datum, it contains some or all bits
+				 * of the current field datum
+				 */
+
+				status = acpi_aml_read_field_data (obj_desc,
+						  this_field_byte_offset + byte_granularity,
+						  bit_granularity, &this_raw_datum);
+				if (ACPI_FAILURE (status)) {
+					goto cleanup;
+				}
+
+				/* Before merging the data, make sure the unused bits are clear */
+
+				switch (byte_granularity)
+				{
+				case 1:
+					this_raw_datum &= 0x000000FF;
+					previous_raw_datum &= 0x000000FF;
+					break;
+
+				case 2:
+					this_raw_datum &= 0x0000FFFF;
+					previous_raw_datum &= 0x0000FFFF;
+					break;
+				}
 			}
 
+
 			/*
 			 * Put together bits of the two raw data to make a complete
 			 * field datum
@@ -391,8 +405,6 @@
 
 	merged_value = field_value;
 
-	/* Check if update rule needs to be applied (not if mask is all ones) */
-
 
 	/* Decode the update rule */
 
@@ -401,13 +413,17 @@
 
 	case UPDATE_PRESERVE:
 
-		/*
-		 * Read the current contents of the byte/word/dword containing
-		 * the field, and merge with the new field value.
-		 */
-		status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset,
-				   bit_granularity, &current_value);
-		merged_value |= (current_value & ~mask);
+		/* Check if update rule needs to be applied (not if mask is all ones) */
+
+		if (((1 << bit_granularity) -1) & ~mask) {
+			/*
+			 * Read the current contents of the byte/word/dword containing
+			 * the field, and merge with the new field value.
+			 */
+			status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset,
+					   bit_granularity, &current_value);
+			merged_value |= (current_value & ~mask);
+		}
 		break;
 
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/ammisc.c linux/drivers/acpi/interpreter/ammisc.c
--- v2.4.0/linux/drivers/acpi/interpreter/ammisc.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/ammisc.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: ammisc - ACPI AML (p-code) execution - specific opcodes
- *              $Revision: 71 $
+ *              $Revision: 73 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -172,7 +172,7 @@
 	if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
 		/* Object to be indexed is a Package */
 
-		if (idx_desc->number.value >= obj_desc->package.count) {
+		if (idx_desc->integer.value >= obj_desc->package.count) {
 			status = AE_AML_PACKAGE_LIMIT;
 			goto cleanup;
 		}
@@ -195,7 +195,7 @@
 			 * we are after.
 			 */
 
-			tmp_desc                      = obj_desc->package.elements[idx_desc->number.value];
+			tmp_desc                      = obj_desc->package.elements[idx_desc->integer.value];
 			ret_desc->reference.op_code   = AML_INDEX_OP;
 			ret_desc->reference.target_type = tmp_desc->common.type;
 			ret_desc->reference.object    = tmp_desc;
@@ -210,13 +210,13 @@
 		 */
 		ret_desc->reference.op_code   = AML_INDEX_OP;
 		ret_desc->reference.target_type = ACPI_TYPE_PACKAGE;
-		ret_desc->reference.where     = &obj_desc->package.elements[idx_desc->number.value];
+		ret_desc->reference.where     = &obj_desc->package.elements[idx_desc->integer.value];
 	}
 
 	else {
 		/* Object to be indexed is a Buffer */
 
-		if (idx_desc->number.value >= obj_desc->buffer.length) {
+		if (idx_desc->integer.value >= obj_desc->buffer.length) {
 			status = AE_AML_BUFFER_LIMIT;
 			goto cleanup;
 		}
@@ -224,7 +224,7 @@
 		ret_desc->reference.op_code     = AML_INDEX_OP;
 		ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
 		ret_desc->reference.object      = obj_desc;
-		ret_desc->reference.offset      = (u32) idx_desc->number.value;
+		ret_desc->reference.offset      = (u32) idx_desc->integer.value;
 
 		status = acpi_aml_exec_store (ret_desc, res_desc, walk_state);
 	}
@@ -314,20 +314,20 @@
 
 	/* Validate match comparison sub-opcodes */
 
-	if ((op1_desc->number.value > MAX_MATCH_OPERATOR) ||
-		(op2_desc->number.value > MAX_MATCH_OPERATOR))
+	if ((op1_desc->integer.value > MAX_MATCH_OPERATOR) ||
+		(op2_desc->integer.value > MAX_MATCH_OPERATOR))
 	{
 		status = AE_AML_OPERAND_VALUE;
 		goto cleanup;
 	}
 
-	index = (u32) start_desc->number.value;
+	index = (u32) start_desc->integer.value;
 	if (index >= (u32) pkg_desc->package.count) {
 		status = AE_AML_PACKAGE_LIMIT;
 		goto cleanup;
 	}
 
-	ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+	ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 	if (!ret_desc) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
@@ -351,7 +351,7 @@
 		 *      should we examine its value?
 		 */
 		if (!pkg_desc->package.elements[index] ||
-			ACPI_TYPE_NUMBER != pkg_desc->package.elements[index]->common.type)
+			ACPI_TYPE_INTEGER != pkg_desc->package.elements[index]->common.type)
 		{
 			continue;
 		}
@@ -362,7 +362,7 @@
 		 *      "continue" (proceed to next iteration of enclosing
 		 *          "for" loop) signifies a non-match.
 		 */
-		switch (op1_desc->number.value)
+		switch (op1_desc->integer.value)
 		{
 
 		case MATCH_MTR:   /* always true */
@@ -372,8 +372,8 @@
 
 		case MATCH_MEQ:   /* true if equal   */
 
-			if (pkg_desc->package.elements[index]->number.value
-				 != V1_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 != V1_desc->integer.value)
 			{
 				continue;
 			}
@@ -382,8 +382,8 @@
 
 		case MATCH_MLE:   /* true if less than or equal  */
 
-			if (pkg_desc->package.elements[index]->number.value
-				 > V1_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 > V1_desc->integer.value)
 			{
 				continue;
 			}
@@ -392,8 +392,8 @@
 
 		case MATCH_MLT:   /* true if less than   */
 
-			if (pkg_desc->package.elements[index]->number.value
-				 >= V1_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 >= V1_desc->integer.value)
 			{
 				continue;
 			}
@@ -402,8 +402,8 @@
 
 		case MATCH_MGE:   /* true if greater than or equal   */
 
-			if (pkg_desc->package.elements[index]->number.value
-				 < V1_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 < V1_desc->integer.value)
 			{
 				continue;
 			}
@@ -412,8 +412,8 @@
 
 		case MATCH_MGT:   /* true if greater than    */
 
-			if (pkg_desc->package.elements[index]->number.value
-				 <= V1_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 <= V1_desc->integer.value)
 			{
 				continue;
 			}
@@ -426,7 +426,7 @@
 		}
 
 
-		switch(op2_desc->number.value)
+		switch(op2_desc->integer.value)
 		{
 
 		case MATCH_MTR:
@@ -436,8 +436,8 @@
 
 		case MATCH_MEQ:
 
-			if (pkg_desc->package.elements[index]->number.value
-				 != V2_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 != V2_desc->integer.value)
 			{
 				continue;
 			}
@@ -446,8 +446,8 @@
 
 		case MATCH_MLE:
 
-			if (pkg_desc->package.elements[index]->number.value
-				 > V2_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 > V2_desc->integer.value)
 			{
 				continue;
 			}
@@ -456,8 +456,8 @@
 
 		case MATCH_MLT:
 
-			if (pkg_desc->package.elements[index]->number.value
-				 >= V2_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 >= V2_desc->integer.value)
 			{
 				continue;
 			}
@@ -466,8 +466,8 @@
 
 		case MATCH_MGE:
 
-			if (pkg_desc->package.elements[index]->number.value
-				 < V2_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 < V2_desc->integer.value)
 			{
 				continue;
 			}
@@ -476,8 +476,8 @@
 
 		case MATCH_MGT:
 
-			if (pkg_desc->package.elements[index]->number.value
-				 <= V2_desc->number.value)
+			if (pkg_desc->package.elements[index]->integer.value
+				 <= V2_desc->integer.value)
 			{
 				continue;
 			}
@@ -497,7 +497,7 @@
 
 	/* Match_value is the return value */
 
-	ret_desc->number.value = match_value;
+	ret_desc->integer.value = match_value;
 
 
 cleanup:
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/ammonad.c linux/drivers/acpi/interpreter/ammonad.c
--- v2.4.0/linux/drivers/acpi/interpreter/ammonad.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/ammonad.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: ammonad - ACPI AML (p-code) execution for monadic operators
- *              $Revision: 88 $
+ *              $Revision: 89 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -180,7 +180,7 @@
 
 	case AML_SLEEP_OP:
 
-		acpi_aml_system_do_suspend ((u32) obj_desc->number.value);
+		acpi_aml_system_do_suspend ((u32) obj_desc->integer.value);
 		break;
 
 
@@ -188,7 +188,7 @@
 
 	case AML_STALL_OP:
 
-		acpi_aml_system_do_stall ((u32) obj_desc->number.value);
+		acpi_aml_system_do_stall ((u32) obj_desc->integer.value);
 		break;
 
 
@@ -267,7 +267,7 @@
 	case AML_TO_BCD_OP:
 	case AML_COND_REF_OF_OP:
 
-		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 		if (!ret_desc) {
 			status = AE_NO_MEMORY;
 			goto cleanup;
@@ -283,7 +283,7 @@
 
 	case AML_BIT_NOT_OP:
 
-		ret_desc->number.value = ~obj_desc->number.value;
+		ret_desc->integer.value = ~obj_desc->integer.value;
 		break;
 
 
@@ -291,17 +291,17 @@
 
 	case AML_FIND_SET_LEFT_BIT_OP:
 
-		ret_desc->number.value = obj_desc->number.value;
+		ret_desc->integer.value = obj_desc->integer.value;
 
 		/*
 		 * Acpi specification describes Integer type as a little
 		 * endian unsigned value, so this boundry condition is valid.
 		 */
-		for (res_val = 0; ret_desc->number.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
-			ret_desc->number.value >>= 1;
+		for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
+			ret_desc->integer.value >>= 1;
 		}
 
-		ret_desc->number.value = res_val;
+		ret_desc->integer.value = res_val;
 		break;
 
 
@@ -309,19 +309,19 @@
 
 	case AML_FIND_SET_RIGHT_BIT_OP:
 
-		ret_desc->number.value = obj_desc->number.value;
+		ret_desc->integer.value = obj_desc->integer.value;
 
 		/*
 		 * Acpi specification describes Integer type as a little
 		 * endian unsigned value, so this boundry condition is valid.
 		 */
-		for (res_val = 0; ret_desc->number.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
-			ret_desc->number.value <<= 1;
+		for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
+			ret_desc->integer.value <<= 1;
 		}
 
 		/* Since returns must be 1-based, subtract from 33 (65) */
 
-		ret_desc->number.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val;
+		ret_desc->integer.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val;
 		break;
 
 
@@ -332,11 +332,11 @@
 		/*
 		 * The 64-bit ACPI integer can hold 16 4-bit BCD integers
 		 */
-		ret_desc->number.value = 0;
+		ret_desc->integer.value = 0;
 		for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
 			/* Get one BCD digit */
 
-			digit = (ACPI_INTEGER) ((obj_desc->number.value >> (i * 4)) & 0xF);
+			digit = (ACPI_INTEGER) ((obj_desc->integer.value >> (i * 4)) & 0xF);
 
 			/* Check the range of the digit */
 
@@ -352,7 +352,7 @@
 					digit *= 10;
 				}
 
-				ret_desc->number.value += digit;
+				ret_desc->integer.value += digit;
 			}
 		}
 		break;
@@ -363,16 +363,16 @@
 	case AML_TO_BCD_OP:
 
 
-		if (obj_desc->number.value > ACPI_MAX_BCD_VALUE) {
+		if (obj_desc->integer.value > ACPI_MAX_BCD_VALUE) {
 			status = AE_AML_NUMERIC_OVERFLOW;
 			goto cleanup;
 		}
 
-		ret_desc->number.value = 0;
+		ret_desc->integer.value = 0;
 		for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
 			/* Divide by nth factor of 10 */
 
-			digit = obj_desc->number.value;
+			digit = obj_desc->integer.value;
 			for (j = 0; j < i; j++) {
 				digit /= 10;
 			}
@@ -380,7 +380,7 @@
 			/* Create the BCD digit */
 
 			if (digit > 0) {
-				ret_desc->number.value += (ACPI_MODULO (digit, 10) << (i * 4));
+				ret_desc->integer.value += (ACPI_MODULO (digit, 10) << (i * 4));
 			}
 		}
 		break;
@@ -402,7 +402,7 @@
 			 * return FALSE
 			 */
 
-			ret_desc->number.value = 0;
+			ret_desc->integer.value = 0;
 
 			/*
 			 * Must delete the result descriptor since there is no reference
@@ -424,7 +424,7 @@
 
 		/* The object exists in the namespace, return TRUE */
 
-		ret_desc->number.value = ACPI_INTEGER_MAX;
+		ret_desc->integer.value = ACPI_INTEGER_MAX;
 		goto cleanup;
 		break;
 
@@ -579,13 +579,13 @@
 
 	case AML_LNOT_OP:
 
-		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 		if (!ret_desc) {
 			status = AE_NO_MEMORY;
 			goto cleanup;
 		}
 
-		ret_desc->number.value = !obj_desc->number.value;
+		ret_desc->integer.value = !obj_desc->integer.value;
 		break;
 
 
@@ -638,10 +638,10 @@
 		/* Do the actual increment or decrement */
 
 		if (AML_INCREMENT_OP == opcode) {
-			ret_desc->number.value++;
+			ret_desc->integer.value++;
 		}
 		else {
-			ret_desc->number.value--;
+			ret_desc->integer.value--;
 		}
 
 		/* Store the result back in the original descriptor */
@@ -672,7 +672,7 @@
 
 				/* Constants are of type Number */
 
-				type = ACPI_TYPE_NUMBER;
+				type = ACPI_TYPE_INTEGER;
 				break;
 
 
@@ -733,13 +733,13 @@
 
 		/* Allocate a descriptor to hold the type. */
 
-		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 		if (!ret_desc) {
 			status = AE_NO_MEMORY;
 			goto cleanup;
 		}
 
-		ret_desc->number.value = type;
+		ret_desc->integer.value = type;
 		break;
 
 
@@ -793,13 +793,13 @@
 		 * object to hold the value
 		 */
 
-		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 		if (!ret_desc) {
 			status = AE_NO_MEMORY;
 			goto cleanup;
 		}
 
-		ret_desc->number.value = value;
+		ret_desc->integer.value = value;
 		break;
 
 
@@ -910,14 +910,14 @@
 					 * sub-buffer of the main buffer, it is only a pointer to a
 					 * single element (byte) of the buffer!
 					 */
-					ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+					ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 					if (!ret_desc) {
 						status = AE_NO_MEMORY;
 						goto cleanup;
 					}
 
 					tmp_desc = obj_desc->reference.object;
-					ret_desc->number.value =
+					ret_desc->integer.value =
 						tmp_desc->buffer.pointer[obj_desc->reference.offset];
 
 					/* TBD: [Investigate] (see below) Don't add an additional
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amnames.c linux/drivers/acpi/interpreter/amnames.c
--- v2.4.0/linux/drivers/acpi/interpreter/amnames.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amnames.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amnames - interpreter/scanner name load/execute
- *              $Revision: 71 $
+ *              $Revision: 73 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amprep.c linux/drivers/acpi/interpreter/amprep.c
--- v2.4.0/linux/drivers/acpi/interpreter/amprep.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amprep.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amprep - ACPI AML (p-code) execution - field prep utilities
- *              $Revision: 72 $
+ *              $Revision: 73 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amregion.c linux/drivers/acpi/interpreter/amregion.c
--- v2.4.0/linux/drivers/acpi/interpreter/amregion.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amregion.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amregion - ACPI default Op_region (address space) handlers
- *              $Revision: 41 $
+ *              $Revision: 44 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -99,8 +99,8 @@
 	 */
 
 	if ((address < mem_info->mapped_physical_address) ||
-		((address + length) >
-			(mem_info->mapped_physical_address + mem_info->mapped_length)))
+		(((ACPI_INTEGER) address + length) >
+			((ACPI_INTEGER) mem_info->mapped_physical_address + mem_info->mapped_length)))
 	{
 		/*
 		 * The request cannot be resolved by the current memory mapping;
@@ -139,7 +139,7 @@
 	/* TBD: should these pointers go to 64-bit in all cases ? */
 
 	logical_addr_ptr = mem_info->mapped_logical_address +
-			  (address - mem_info->mapped_physical_address);
+			  ((ACPI_INTEGER) address - (ACPI_INTEGER) mem_info->mapped_physical_address);
 
 	/* Perform the memory read or write */
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amresnte.c linux/drivers/acpi/interpreter/amresnte.c
--- v2.4.0/linux/drivers/acpi/interpreter/amresnte.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amresnte.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amresnte - AML Interpreter object resolution
- *              $Revision: 25 $
+ *              $Revision: 27 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -55,7 +55,7 @@
  * can be either a pointer to an actual internal object or a pointer into the
  * AML stream itself.  These types are currently:
  *
- *      ACPI_TYPE_NUMBER
+ *      ACPI_TYPE_INTEGER
  *      ACPI_TYPE_STRING
  *      ACPI_TYPE_BUFFER
  *      ACPI_TYPE_MUTEX
@@ -208,14 +208,14 @@
 		break;
 
 
-	case ACPI_TYPE_NUMBER:
+	case ACPI_TYPE_INTEGER:
 
 		/*
 		 * The Node has an attached internal object, make sure that it's a
 		 * number
 		 */
 
-		if (ACPI_TYPE_NUMBER != val_desc->common.type) {
+		if (ACPI_TYPE_INTEGER != val_desc->common.type) {
 			return (AE_AML_OPERAND_TYPE);
 		}
 
@@ -244,7 +244,7 @@
 			object_type = ACPI_TYPE_BUFFER;
 		}
 		else {
-			object_type = ACPI_TYPE_NUMBER;
+			object_type = ACPI_TYPE_INTEGER;
 		}
 
 		/*
@@ -282,7 +282,7 @@
 				return (status);
 			}
 
-			obj_desc->number.value = temp_val;
+			obj_desc->integer.value = temp_val;
 		}
 
 
@@ -330,12 +330,12 @@
 
 		/* Create an object for the result */
 
-		obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+		obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 		if (!obj_desc) {
 			return (AE_NO_MEMORY);
 		}
 
-		obj_desc->number.value = temp_val;
+		obj_desc->integer.value = temp_val;
 		break;
 
 
@@ -378,12 +378,12 @@
 
 		/* Create an object for the result */
 
-		obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+		obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 		if (!obj_desc) {
 			return (AE_NO_MEMORY);
 		}
 
-		obj_desc->number.value = temp_val;
+		obj_desc->integer.value = temp_val;
 		break;
 
 
@@ -477,12 +477,12 @@
 
 		/* Create object for result */
 
-		obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
+		obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
 		if (!obj_desc) {
 			return (AE_NO_MEMORY);
 		}
 
-		obj_desc->number.value = temp_val;
+		obj_desc->integer.value = temp_val;
 
 		/* Truncate value if we are executing from a 32-bit ACPI table */
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amresolv.c linux/drivers/acpi/interpreter/amresolv.c
--- v2.4.0/linux/drivers/acpi/interpreter/amresolv.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amresolv.c	Mon Jan 29 10:15:59 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amresolv - AML Interpreter object resolution
- *              $Revision: 78 $
+ *              $Revision: 81 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -118,19 +118,19 @@
 		mask = ACPI_UINT32_MAX;
 	}
 
-	result_desc->number.type = (u8) ACPI_TYPE_NUMBER;
+	result_desc->integer.type = (u8) ACPI_TYPE_INTEGER;
 
 	/* Get the 32 bit value at the location */
 
-	MOVE_UNALIGNED32_TO_32 (&result_desc->number.value, location);
+	MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location);
 
 	/*
 	 * Shift the 32-bit word containing the field, and mask off the
 	 * resulting value
 	 */
 
-	result_desc->number.value =
-		(result_desc->number.value >> field_desc->field_unit.bit_offset) & mask;
+	result_desc->integer.value =
+		(result_desc->integer.value >> field_desc->field_unit.bit_offset) & mask;
 
 	/* Release global lock if we acquired it earlier */
 
@@ -150,7 +150,7 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Convert Reference entries on Obj_stack to Rvalues
+ * DESCRIPTION: Convert Reference objects to values
  *
  ******************************************************************************/
 
@@ -279,7 +279,7 @@
 			acpi_cm_remove_reference (stack_desc);
 			*stack_ptr = obj_desc;
 
-			if (ACPI_TYPE_NUMBER == obj_desc->common.type) {
+			if (ACPI_TYPE_INTEGER == obj_desc->common.type) {
 				/* Value is a Number */
 
 			}
@@ -311,7 +311,7 @@
 			acpi_cm_remove_reference (stack_desc);
 			*stack_ptr = obj_desc;
 
-			if (ACPI_TYPE_NUMBER == obj_desc->common.type) {
+			if (ACPI_TYPE_INTEGER == obj_desc->common.type) {
 				/* Value is a Number */
 
 			}
@@ -326,22 +326,22 @@
 
 		case AML_ZERO_OP:
 
-			stack_desc->common.type = (u8) ACPI_TYPE_NUMBER;
-			stack_desc->number.value = 0;
+			stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
+			stack_desc->integer.value = 0;
 			break;
 
 
 		case AML_ONE_OP:
 
-			stack_desc->common.type = (u8) ACPI_TYPE_NUMBER;
-			stack_desc->number.value = 1;
+			stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
+			stack_desc->integer.value = 1;
 			break;
 
 
 		case AML_ONES_OP:
 
-			stack_desc->common.type = (u8) ACPI_TYPE_NUMBER;
-			stack_desc->number.value = ACPI_INTEGER_MAX;
+			stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
+			stack_desc->integer.value = ACPI_INTEGER_MAX;
 
 			/* Truncate value if we are executing from a 32-bit ACPI table */
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amresop.c linux/drivers/acpi/interpreter/amresop.c
--- v2.4.0/linux/drivers/acpi/interpreter/amresop.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amresop.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amresop - AML Interpreter operand/object resolution
- *              $Revision: 18 $
+ *              $Revision: 22 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -214,8 +214,13 @@
 		switch (this_arg_type)
 		{
 
-		case ARGI_REFERENCE:   /* Reference */
-		case ARGI_TARGETREF:
+		case ARGI_REFERENCE:            /* References */
+		case ARGI_INTEGER_REF:
+		case ARGI_OBJECT_REF:
+		case ARGI_DEVICE_REF:
+		case ARGI_TARGETREF:            /* TBD: must implement implicit conversion rules before store */
+		case ARGI_FIXED_TARGET:         /* No implicit conversion before store to target */
+		case ARGI_SIMPLE_TARGET:        /* Name, Local, or Arg - no implicit conversion */
 
 			/* Need an operand of type INTERNAL_TYPE_REFERENCE */
 
@@ -283,20 +288,6 @@
 		 * For the simple cases, only one type of resolved object
 		 * is allowed
 		 */
-		case ARGI_NUMBER:   /* Number */
-
-			/* Need an operand of type ACPI_TYPE_NUMBER */
-
-			type_needed = ACPI_TYPE_NUMBER;
-			break;
-
-		case ARGI_BUFFER:
-
-			/* Need an operand of type ACPI_TYPE_BUFFER */
-
-			type_needed = ACPI_TYPE_BUFFER;
-			break;
-
 		case ARGI_MUTEX:
 
 			/* Need an operand of type ACPI_TYPE_MUTEX */
@@ -344,11 +335,69 @@
 		 * The more complex cases allow multiple resolved object types
 		 */
 
+		case ARGI_INTEGER:   /* Number */
+
+			/*
+			 * Need an operand of type ACPI_TYPE_INTEGER,
+			 * But we can implicitly convert from a STRING or BUFFER
+			 */
+			status = acpi_aml_convert_to_integer (stack_ptr, walk_state);
+			if (ACPI_FAILURE (status)) {
+				if (status == AE_TYPE) {
+					return (AE_AML_OPERAND_TYPE);
+				}
+
+				return (status);
+			}
+
+			goto next_operand;
+			break;
+
+
+		case ARGI_BUFFER:
+
+			/*
+			 * Need an operand of type ACPI_TYPE_BUFFER,
+			 * But we can implicitly convert from a STRING or INTEGER
+			 */
+			status = acpi_aml_convert_to_buffer (stack_ptr, walk_state);
+			if (ACPI_FAILURE (status)) {
+				if (status == AE_TYPE) {
+					return (AE_AML_OPERAND_TYPE);
+				}
+
+				return (status);
+			}
+
+			goto next_operand;
+			break;
+
+
 		case ARGI_STRING:
 
-			/* Need an operand of type ACPI_TYPE_STRING or ACPI_TYPE_BUFFER */
+			/*
+			 * Need an operand of type ACPI_TYPE_STRING,
+			 * But we can implicitly convert from a BUFFER or INTEGER
+			 */
+			status = acpi_aml_convert_to_string (stack_ptr, walk_state);
+			if (ACPI_FAILURE (status)) {
+				if (status == AE_TYPE) {
+					return (AE_AML_OPERAND_TYPE);
+				}
+
+				return (status);
+			}
+
+			goto next_operand;
+			break;
+
+
+		case ARGI_COMPUTEDATA:
+
+			/* Need an operand of type INTEGER, STRING or BUFFER */
 
-			if ((ACPI_TYPE_STRING != (*stack_ptr)->common.type) &&
+			if ((ACPI_TYPE_INTEGER != (*stack_ptr)->common.type) &&
+				(ACPI_TYPE_STRING != (*stack_ptr)->common.type) &&
 				(ACPI_TYPE_BUFFER != (*stack_ptr)->common.type))
 			{
 				return (AE_AML_OPERAND_TYPE);
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amstore.c linux/drivers/acpi/interpreter/amstore.c
--- v2.4.0/linux/drivers/acpi/interpreter/amstore.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amstore.c	Mon Jan 29 10:15:59 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amstore - AML Interpreter object store support
- *              $Revision: 117 $
+ *              $Revision: 121 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -64,12 +64,7 @@
 	ACPI_WALK_STATE         *walk_state)
 {
 	ACPI_STATUS             status = AE_OK;
-	ACPI_OPERAND_OBJECT     *delete_dest_desc = NULL;
-	ACPI_OPERAND_OBJECT     *tmp_desc;
-	ACPI_NAMESPACE_NODE     *node = NULL;
-	u8                      value = 0;
-	u32                     length;
-	u32                     i;
+	ACPI_OPERAND_OBJECT     *ref_desc = dest_desc;
 
 
 	/* Validate parameters */
@@ -78,27 +73,23 @@
 		return (AE_AML_NO_OPERAND);
 	}
 
-	/* Examine the datatype of the Dest_desc */
+	/* Dest_desc can be either a namespace node or an ACPI object */
 
 	if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) {
-		/* Dest is an ACPI_HANDLE, create a new object */
-
-		node = (ACPI_NAMESPACE_NODE *) dest_desc;
-		dest_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
-		if (!dest_desc) {
-			/* Allocation failure  */
-
-			return (AE_NO_MEMORY);
-		}
+		/*
+		 * Dest is a namespace node,
+		 * Storing an object into a Name "container"
+		 */
+		status = acpi_aml_store_object_to_node (val_desc,
+				 (ACPI_NAMESPACE_NODE *) dest_desc, walk_state);
 
-		/* Build a new Reference wrapper around the handle */
+		/* All done, that's it */
 
-		dest_desc->reference.op_code = AML_NAME_OP;
-		dest_desc->reference.object = node;
+		return (status);
 	}
 
 
-	/* Destination object must be of type Reference */
+	/* Destination object must be an object of type Reference */
 
 	if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) {
 		/* Destination is not an Reference */
@@ -106,36 +97,130 @@
 		return (AE_AML_OPERAND_TYPE);
 	}
 
-	/* Examine the Reference opcode */
 
-	switch (dest_desc->reference.op_code)
+	/*
+	 * Examine the Reference opcode.  These cases are handled:
+	 *
+	 * 1) Store to Name (Change the object associated with a name)
+	 * 2) Store to an indexed area of a Buffer or Package
+	 * 3) Store to a Method Local or Arg
+	 * 4) Store to the debug object
+	 * 5) Store to a constant -- a noop
+	 */
+
+	switch (ref_desc->reference.op_code)
 	{
 
 	case AML_NAME_OP:
 
-		/*
-		 *  Storing into a Name
-		 */
-		delete_dest_desc = dest_desc;
-		status = acpi_aml_store_object_to_node (val_desc, dest_desc->reference.object,
-				  walk_state);
+		/* Storing an object into a Name "container" */
 
-		break;  /* Case Name_op */
+		status = acpi_aml_store_object_to_node (val_desc, ref_desc->reference.object,
+				  walk_state);
+		break;
 
 
 	case AML_INDEX_OP:
 
-		delete_dest_desc = dest_desc;
+		/* Storing to an Index (pointer into a packager or buffer) */
+
+		status = acpi_aml_store_object_to_index (val_desc, ref_desc, walk_state);
+		break;
+
+
+	case AML_LOCAL_OP:
+
+		status = acpi_ds_method_data_set_value (MTH_TYPE_LOCAL,
+				  (ref_desc->reference.offset), val_desc, walk_state);
+		break;
+
+
+	case AML_ARG_OP:
+
+		status = acpi_ds_method_data_set_value (MTH_TYPE_ARG,
+				  (ref_desc->reference.offset), val_desc, walk_state);
+		break;
+
+
+	case AML_DEBUG_OP:
 
 		/*
-		 * Valid source value and destination reference pointer.
+		 * Storing to the Debug object causes the value stored to be
+		 * displayed and otherwise has no effect -- see ACPI Specification
 		 *
-		 * ACPI Specification 1.0B section 15.2.3.4.2.13:
-		 * Destination should point to either a buffer or a package
+		 * TBD: print known object types "prettier".
 		 */
 
+		break;
+
+
+	case AML_ZERO_OP:
+	case AML_ONE_OP:
+	case AML_ONES_OP:
+
 		/*
-		 * Actually, storing to a package is not so simple.  The source must be
+		 * Storing to a constant is a no-op -- see ACPI Specification
+		 * Delete the reference descriptor, however
+		 */
+		break;
+
+
+	default:
+
+		/* TBD: [Restructure] use object dump routine !! */
+
+		status = AE_AML_INTERNAL;
+		break;
+
+	}   /* switch (Ref_desc->Reference.Op_code) */
+
+
+	/* Always delete the reference descriptor object */
+
+	if (ref_desc) {
+		acpi_cm_remove_reference (ref_desc);
+	}
+
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_store_object_to_index
+ *
+ * PARAMETERS:  *Val_desc           - Value to be stored
+ *              *Node           - Named object to recieve the value
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Store the object to the named object.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_store_object_to_index (
+	ACPI_OPERAND_OBJECT     *val_desc,
+	ACPI_OPERAND_OBJECT     *dest_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_STATUS             status = AE_OK;
+	ACPI_OPERAND_OBJECT     *obj_desc;
+	u32                     length;
+	u32                     i;
+	u8                      value = 0;
+
+
+	/*
+	 * Destination must be a reference pointer, and
+	 * must point to either a buffer or a package
+	 */
+
+	switch (dest_desc->reference.target_type)
+	{
+	case ACPI_TYPE_PACKAGE:
+		/*
+		 * Storing to a package element is not simple.  The source must be
 		 * evaluated and converted to the type of the destination and then the
 		 * source is copied into the destination - we can't just point to the
 		 * source object.
@@ -145,8 +230,8 @@
 			 * The object at *(Dest_desc->Reference.Where) is the
 			 *  element within the package that is to be modified.
 			 */
-			tmp_desc = *(dest_desc->reference.where);
-			if (tmp_desc) {
+			obj_desc = *(dest_desc->reference.where);
+			if (obj_desc) {
 				/*
 				 * If the Destination element is a package, we will delete
 				 *  that object and construct a new one.
@@ -155,41 +240,39 @@
 				 *      to be packages?
 				 *       && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE)
 				 */
-				if (tmp_desc->common.type == ACPI_TYPE_PACKAGE) {
+				if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
 					/*
 					 * Take away the reference for being part of a package and
 					 * delete
 					 */
-					acpi_cm_remove_reference (tmp_desc);
-					acpi_cm_remove_reference (tmp_desc);
+					acpi_cm_remove_reference (obj_desc);
+					acpi_cm_remove_reference (obj_desc);
 
-					tmp_desc = NULL;
+					obj_desc = NULL;
 				}
 			}
 
-			if (!tmp_desc) {
+			if (!obj_desc) {
 				/*
-				 * If the Tmp_desc is NULL, that means an uninitialized package
-				 * has been used as a destination, therefore, we must create
-				 * the destination element to match the type of the source
-				 * element NOTE: Val_desc can be of any type.
+				 * If the Obj_desc is NULL, it means that an uninitialized package
+				 * element has been used as a destination (this is OK), therefore,
+				 * we must create the destination element to match the type of the
+				 * source element NOTE: Val_desc can be of any type.
 				 */
-				tmp_desc = acpi_cm_create_internal_object (val_desc->common.type);
-				if (!tmp_desc) {
-					status = AE_NO_MEMORY;
-					goto cleanup;
+				obj_desc = acpi_cm_create_internal_object (val_desc->common.type);
+				if (!obj_desc) {
+					return (AE_NO_MEMORY);
 				}
 
 				/*
 				 * If the source is a package, copy the source to the new dest
 				 */
-				if (ACPI_TYPE_PACKAGE == tmp_desc->common.type) {
+				if (ACPI_TYPE_PACKAGE == obj_desc->common.type) {
 					status = acpi_aml_build_copy_internal_package_object (
-							 val_desc, tmp_desc, walk_state);
+							 val_desc, obj_desc, walk_state);
 					if (ACPI_FAILURE (status)) {
-						acpi_cm_remove_reference (tmp_desc);
-						tmp_desc = NULL;
-						goto cleanup;
+						acpi_cm_remove_reference (obj_desc);
+						return (status);
 					}
 				}
 
@@ -199,38 +282,31 @@
 				 * part of the parent package
 				 */
 
-				*(dest_desc->reference.where) = tmp_desc;
-				acpi_cm_add_reference (tmp_desc);
+				*(dest_desc->reference.where) = obj_desc;
+				acpi_cm_add_reference (obj_desc);
 			}
 
-			if (ACPI_TYPE_PACKAGE != tmp_desc->common.type) {
+			if (ACPI_TYPE_PACKAGE != obj_desc->common.type) {
 				/*
 				 * The destination element is not a package, so we need to
 				 * convert the contents of the source (Val_desc) and copy into
-				 * the destination (Tmp_desc)
+				 * the destination (Obj_desc)
 				 */
-				status = acpi_aml_store_object_to_object (val_desc, tmp_desc,
+				status = acpi_aml_store_object_to_object (val_desc, obj_desc,
 						  walk_state);
 				if (ACPI_FAILURE (status)) {
 					/*
 					 * An error occurrered when copying the internal object
 					 * so delete the reference.
 					 */
-					status = AE_AML_OPERAND_TYPE;
+					return (AE_AML_OPERAND_TYPE);
 				}
 			}
-
-			break;
 		}
+		break;
 
-		/*
-		 * Check that the destination is a Buffer Field type
-		 */
-		if (dest_desc->reference.target_type != ACPI_TYPE_BUFFER_FIELD) {
-			status = AE_AML_OPERAND_TYPE;
-			break;
-		}
 
+	case ACPI_TYPE_BUFFER_FIELD:
 		/*
 		 * Storing into a buffer at a location defined by an Index.
 		 *
@@ -239,13 +315,11 @@
 		 */
 
 		/*
-		 * Set the Tmp_desc to the destination object and type check.
+		 * Set the Obj_desc to the destination object and type check.
 		 */
-		tmp_desc = dest_desc->reference.object;
-
-		if (tmp_desc->common.type != ACPI_TYPE_BUFFER) {
-			status = AE_AML_OPERAND_TYPE;
-			break;
+		obj_desc = dest_desc->reference.object;
+		if (obj_desc->common.type != ACPI_TYPE_BUFFER) {
+			return (AE_AML_OPERAND_TYPE);
 		}
 
 		/*
@@ -256,15 +330,15 @@
 		switch (val_desc->common.type)
 		{
 		/*
-		 * If the type is Integer, the Length is 4.
+		 * If the type is Integer, assign bytewise
 		 * This loop to assign each of the elements is somewhat
-		 *  backward because of the Big Endian-ness of IA-64
+		 * backward because of the Big Endian-ness of IA-64
 		 */
-		case ACPI_TYPE_NUMBER:
-			length = 4;
+		case ACPI_TYPE_INTEGER:
+			length = sizeof (ACPI_INTEGER);
 			for (i = length; i != 0; i--) {
-				value = (u8)(val_desc->number.value >> (MUL_8 (i - 1)));
-				tmp_desc->buffer.pointer[dest_desc->reference.offset] = value;
+				value = (u8)(val_desc->integer.value >> (MUL_8 (i - 1)));
+				obj_desc->buffer.pointer[dest_desc->reference.offset] = value;
 			}
 			break;
 
@@ -276,7 +350,7 @@
 			length = val_desc->buffer.length;
 			for (i = 0; i < length; i++) {
 				value = *(val_desc->buffer.pointer + i);
-				tmp_desc->buffer.pointer[dest_desc->reference.offset] = value;
+				obj_desc->buffer.pointer[dest_desc->reference.offset] = value;
 			}
 			break;
 
@@ -288,7 +362,7 @@
 			length = val_desc->string.length;
 			for (i = 0; i < length; i++) {
 				value = *(val_desc->string.pointer + i);
-				tmp_desc->buffer.pointer[dest_desc->reference.offset] = value;
+				obj_desc->buffer.pointer[dest_desc->reference.offset] = value;
 			}
 			break;
 
@@ -299,80 +373,207 @@
 			status = AE_AML_OPERAND_TYPE;
 			break;
 		}
+		break;
 
-		/*
-		 * If we had an error, break out of this case statement.
-		 */
-		if (ACPI_FAILURE (status)) {
-			break;
-		}
-
-		/*
-		 * Set the return pointer
-		 */
-		dest_desc = tmp_desc;
 
+	default:
+		status = AE_AML_OPERAND_TYPE;
 		break;
+	}
 
-	case AML_ZERO_OP:
-	case AML_ONE_OP:
-	case AML_ONES_OP:
 
-		/*
-		 * Storing to a constant is a no-op -- see ACPI Specification
-		 * Delete the result descriptor.
-		 */
+	return (status);
+}
 
-		delete_dest_desc = dest_desc;
-		break;
 
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_store_object_to_node
+ *
+ * PARAMETERS:  *Source_desc           - Value to be stored
+ *              *Node               - Named object to recieve the value
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Store the object to the named object.
+ *
+ *              The Assignment of an object to a named object is handled here
+ *              The val passed in will replace the current value (if any)
+ *              with the input value.
+ *
+ *              When storing into an object the data is converted to the
+ *              target object type then stored in the object.  This means
+ *              that the target object type (for an initialized target) will
+ *              not be changed by a store operation.
+ *
+ *              NOTE: the global lock is acquired early.  This will result
+ *              in the global lock being held a bit longer.  Also, if the
+ *              function fails during set up we may get the lock when we
+ *              don't really need it.  I don't think we care.
+ *
+ ******************************************************************************/
 
-	case AML_LOCAL_OP:
+ACPI_STATUS
+acpi_aml_store_object_to_node (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_NAMESPACE_NODE     *node,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_STATUS             status = AE_OK;
+	ACPI_OPERAND_OBJECT     *target_desc;
+	OBJECT_TYPE_INTERNAL    target_type = ACPI_TYPE_ANY;
 
-		status = acpi_ds_method_data_set_value (MTH_TYPE_LOCAL,
-				  (dest_desc->reference.offset), val_desc, walk_state);
-		delete_dest_desc = dest_desc;
-		break;
 
+	/*
+	 * Assuming the parameters were already validated
+	 */
+	ACPI_ASSERT((node) && (source_desc));
+
+
+	/*
+	 * Get current type of the node, and object attached to Node
+	 */
+	target_type = acpi_ns_get_type (node);
+	target_desc = acpi_ns_get_attached_object (node);
+
+
+	/*
+	 * Resolve the source object to an actual value
+	 * (If it is a reference object)
+	 */
+	status = acpi_aml_resolve_object (&source_desc, target_type, walk_state);
+	if (ACPI_FAILURE (status)) {
+		return (status);
+	}
 
-	case AML_ARG_OP:
 
-		status = acpi_ds_method_data_set_value (MTH_TYPE_ARG,
-				  (dest_desc->reference.offset), val_desc, walk_state);
-		delete_dest_desc = dest_desc;
+	/*
+	 * Do the actual store operation
+	 */
+	switch (target_type)
+	{
+	case INTERNAL_TYPE_DEF_FIELD:
+
+		/* Raw data copy for target types Integer/String/Buffer */
+
+		status = acpi_aml_copy_data_to_named_field (source_desc, node);
 		break;
 
 
-	case AML_DEBUG_OP:
+	case ACPI_TYPE_INTEGER:
+	case ACPI_TYPE_STRING:
+	case ACPI_TYPE_BUFFER:
+	case INTERNAL_TYPE_BANK_FIELD:
+	case INTERNAL_TYPE_INDEX_FIELD:
+	case ACPI_TYPE_FIELD_UNIT:
 
 		/*
-		 * Storing to the Debug object causes the value stored to be
-		 * displayed and otherwise has no effect -- see ACPI Specification
+		 * These target types are all of type Integer/String/Buffer, and
+		 * therefore support implicit conversion before the store.
+		 *
+		 * Copy and/or convert the source object to a new target object
 		 */
+		status = acpi_aml_store_object (source_desc, target_type, &target_desc, walk_state);
+		if (ACPI_FAILURE (status)) {
+			return (status);
+		}
 
-		delete_dest_desc = dest_desc;
+		/*
+		 * Store the new Target_desc as the new value of the Name, and set
+		 * the Name's type to that of the value being stored in it.
+		 * Source_desc reference count is incremented by Attach_object.
+		 */
+		status = acpi_ns_attach_object (node, target_desc, target_type);
 		break;
 
 
 	default:
 
-		/* TBD: [Restructure] use object dump routine !! */
+		/* No conversions for all other types.  Just attach the source object */
 
-		delete_dest_desc = dest_desc;
-		status = AE_AML_INTERNAL;
+		status = acpi_ns_attach_object (node, source_desc, source_desc->common.type);
+
+		break;
+	}
+
+
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_store_object_to_object
+ *
+ * PARAMETERS:  *Source_desc           - Value to be stored
+ *              *Dest_desc          - Object to receive the value
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Store an object to another object.
+ *
+ *              The Assignment of an object to another (not named) object
+ *              is handled here.
+ *              The val passed in will replace the current value (if any)
+ *              with the input value.
+ *
+ *              When storing into an object the data is converted to the
+ *              target object type then stored in the object.  This means
+ *              that the target object type (for an initialized target) will
+ *              not be changed by a store operation.
+ *
+ *              This module allows destination types of Number, String,
+ *              and Buffer.
+ *
+ ******************************************************************************/
 
-	}   /* switch(Dest_desc->Reference.Op_code) */
+ACPI_STATUS
+acpi_aml_store_object_to_object (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *dest_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_STATUS             status = AE_OK;
+	OBJECT_TYPE_INTERNAL    destination_type = dest_desc->common.type;
 
 
-cleanup:
+	/*
+	 *  Assuming the parameters are valid!
+	 */
+	ACPI_ASSERT((dest_desc) && (source_desc));
 
-	/* Cleanup and exit*/
 
-	if (delete_dest_desc) {
-		acpi_cm_remove_reference (delete_dest_desc);
+	/*
+	 * From this interface, we only support Integers/Strings/Buffers
+	 */
+	switch (destination_type)
+	{
+	case ACPI_TYPE_INTEGER:
+	case ACPI_TYPE_STRING:
+	case ACPI_TYPE_BUFFER:
+		break;
+
+	default:
+		return (AE_NOT_IMPLEMENTED);
 	}
 
+
+	/*
+	 * Resolve the source object to an actual value
+	 * (If it is a reference object)
+	 */
+	status = acpi_aml_resolve_object (&source_desc, destination_type, walk_state);
+	if (ACPI_FAILURE (status)) {
+		return (status);
+	}
+
+
+	/*
+	 * Copy and/or convert the source object to the destination object
+	 */
+	status = acpi_aml_store_object (source_desc, destination_type, &dest_desc, walk_state);
+
+
 	return (status);
 }
-
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amstoren.c linux/drivers/acpi/interpreter/amstoren.c
--- v2.4.0/linux/drivers/acpi/interpreter/amstoren.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amstoren.c	Mon Jan 29 10:15:59 2001
@@ -2,13 +2,13 @@
 /******************************************************************************
  *
  * Module Name: amstoren - AML Interpreter object store support,
- *                         Store to Node (namespace object)
- *              $Revision: 24 $
+ *                        Store to Node (namespace object)
+ *              $Revision: 28 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -41,127 +41,72 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_aml_store_object_to_node
+ * FUNCTION:    Acpi_aml_resolve_object
  *
- * PARAMETERS:  *Val_desc           - Value to be stored
- *              *Node           - Named object to recieve the value
+ * PARAMETERS:  Source_desc_ptr     - Pointer to the source object
+ *              Target_type         - Current type of the target
+ *              Walk_state          - Current walk state
  *
- * RETURN:      Status
- *
- * DESCRIPTION: Store the object to the named object.
+ * RETURN:      Status, resolved object in Source_desc_ptr.
  *
- *              The Assignment of an object to a named object is handled here
- *              The val passed in will replace the current value (if any)
- *              with the input value.
- *
- *              When storing into an object the data is converted to the
- *              target object type then stored in the object.  This means
- *              that the target object type (for an initialized target) will
- *              not be changed by a store operation.
- *
- *              NOTE: the global lock is acquired early.  This will result
- *              in the global lock being held a bit longer.  Also, if the
- *              function fails during set up we may get the lock when we
- *              don't really need it.  I don't think we care.
+ * DESCRIPTION: Resolve an object.  If the object is a reference, dereference
+ *              it and return the actual object in the Source_desc_ptr.
  *
  ******************************************************************************/
 
 ACPI_STATUS
-acpi_aml_store_object_to_node (
-	ACPI_OPERAND_OBJECT     *val_desc,
-	ACPI_NAMESPACE_NODE     *node,
+acpi_aml_resolve_object (
+	ACPI_OPERAND_OBJECT     **source_desc_ptr,
+	OBJECT_TYPE_INTERNAL    target_type,
 	ACPI_WALK_STATE         *walk_state)
 {
+	ACPI_OPERAND_OBJECT     *source_desc = *source_desc_ptr;
 	ACPI_STATUS             status = AE_OK;
-	u8                      *buffer = NULL;
-	u32                     length = 0;
-	u32                     mask;
-	u32                     new_value;
-	u8                      locked = FALSE;
-	u8                      *location=NULL;
-	ACPI_OPERAND_OBJECT     *dest_desc;
-	OBJECT_TYPE_INTERNAL    destination_type = ACPI_TYPE_ANY;
 
 
 	/*
-	 *  Assuming the parameters are valid!!!
+	 * Ensure we have a Source that can be stored in the target
 	 */
-	ACPI_ASSERT((node) && (val_desc));
+	switch (target_type)
+	{
 
-	destination_type = acpi_ns_get_type (node);
+	/* This case handles the "interchangeable" types Integer, String, and Buffer. */
 
 	/*
-	 *  First ensure we have a value that can be stored in the target
+	 * These cases all require only Integers or values that
+	 * can be converted to Integers (Strings or Buffers)
 	 */
-	switch (destination_type)
-	{
-		/* Type of Name's existing value */
-
-	case INTERNAL_TYPE_ALIAS:
-
-		/*
-		 *  Aliases are resolved by Acpi_aml_prep_operands
-		 */
-
-		status = AE_AML_INTERNAL;
-		break;
-
-
+	case ACPI_TYPE_INTEGER:
+	case ACPI_TYPE_FIELD_UNIT:
 	case INTERNAL_TYPE_BANK_FIELD:
 	case INTERNAL_TYPE_INDEX_FIELD:
-	case ACPI_TYPE_FIELD_UNIT:
-	case ACPI_TYPE_NUMBER:
-
-		/*
-		 *  These cases all require only number values or values that
-		 *  can be converted to numbers.
-		 *
-		 *  If value is not a Number, try to resolve it to one.
-		 */
-
-		if (val_desc->common.type != ACPI_TYPE_NUMBER) {
-			/*
-			 *  Initially not a number, convert
-			 */
-			status = acpi_aml_resolve_to_value (&val_desc, walk_state);
-			if (ACPI_SUCCESS (status) &&
-				(val_desc->common.type != ACPI_TYPE_NUMBER))
-			{
-				/*
-				 *  Conversion successful but still not a number
-				 */
-				status = AE_AML_OPERAND_TYPE;
-			}
-		}
-
-		break;
 
+	/*
+	 * Stores into a Field/Region or into a Buffer/String
+	 * are all essentially the same.
+	 */
 	case ACPI_TYPE_STRING:
 	case ACPI_TYPE_BUFFER:
 	case INTERNAL_TYPE_DEF_FIELD:
 
 		/*
-		 *  Storing into a Field in a region or into a buffer or into
-		 *  a string all is essentially the same.
-		 *
-		 *  If value is not a valid type, try to resolve it to one.
+		 * If Source_desc is not a valid type, try to resolve it to one.
 		 */
-
-		if ((val_desc->common.type != ACPI_TYPE_NUMBER) &&
-			(val_desc->common.type != ACPI_TYPE_BUFFER) &&
-			(val_desc->common.type != ACPI_TYPE_STRING))
+		if ((source_desc->common.type != ACPI_TYPE_INTEGER)    &&
+			(source_desc->common.type != ACPI_TYPE_BUFFER)     &&
+			(source_desc->common.type != ACPI_TYPE_STRING))
 		{
 			/*
-			 *  Initially not a valid type, convert
+			 * Initially not a valid type, convert
 			 */
-			status = acpi_aml_resolve_to_value (&val_desc, walk_state);
+			status = acpi_aml_resolve_to_value (source_desc_ptr, walk_state);
 			if (ACPI_SUCCESS (status) &&
-				(val_desc->common.type != ACPI_TYPE_NUMBER) &&
-				(val_desc->common.type != ACPI_TYPE_BUFFER) &&
-				(val_desc->common.type != ACPI_TYPE_STRING))
+				(source_desc->common.type != ACPI_TYPE_INTEGER)    &&
+				(source_desc->common.type != ACPI_TYPE_BUFFER)     &&
+				(source_desc->common.type != ACPI_TYPE_STRING))
 			{
 				/*
-				 *  Conversion successful but still not a valid type
+				 * Conversion successful but still not a valid type
 				 */
 				status = AE_AML_OPERAND_TYPE;
 			}
@@ -169,347 +114,133 @@
 		break;
 
 
-	case ACPI_TYPE_PACKAGE:
+	case INTERNAL_TYPE_ALIAS:
 
 		/*
-		 *  TBD: [Unhandled] Not real sure what to do here
+		 * Aliases are resolved by Acpi_aml_prep_operands
 		 */
-		status = AE_NOT_IMPLEMENTED;
+		status = AE_AML_INTERNAL;
 		break;
 
 
+	case ACPI_TYPE_PACKAGE:
 	default:
 
 		/*
-		 * All other types than Alias and the various Fields come here.
-		 * Store Val_desc as the new value of the Name, and set
-		 * the Name's type to that of the value being stored in it.
-		 * Val_desc reference count is incremented by Attach_object.
+		 * All other types than Alias and the various Fields come here,
+		 * including the untyped case - ACPI_TYPE_ANY.
 		 */
-
-		status = acpi_ns_attach_object (node, val_desc, val_desc->common.type);
-
-		goto clean_up_and_bail_out;
 		break;
 	}
 
-	/* Exit now if failure above */
+	return (status);
+}
 
-	if (ACPI_FAILURE (status)) {
-		goto clean_up_and_bail_out;
-	}
 
-	/*
-	 *  Get descriptor for object attached to Node
-	 */
-	dest_desc = acpi_ns_get_attached_object (node);
-	if (!dest_desc) {
-		/*
-		 *  There is no existing object attached to this Node
-		 */
-		status = AE_AML_INTERNAL;
-		goto clean_up_and_bail_out;
-	}
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_store_object
+ *
+ * PARAMETERS:  Source_desc         - Object to store
+ *              Target_type         - Current type of the target
+ *              Target_desc_ptr     - Pointer to the target
+ *              Walk_state          - Current walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: "Store" an object to another object.  This may include
+ *              converting the source type to the target type (implicit
+ *              conversion), and a copy of the value of the source to
+ *              the target.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_store_object (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	OBJECT_TYPE_INTERNAL    target_type,
+	ACPI_OPERAND_OBJECT     **target_desc_ptr,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_OPERAND_OBJECT     *target_desc = *target_desc_ptr;
+	ACPI_STATUS             status;
+
 
 	/*
-	 *  Make sure the destination Object is the same as the Node
+	 * Perform the "implicit conversion" of the source to the current type
+	 * of the target - As per the ACPI specification.
+	 *
+	 * If no conversion performed, Source_desc is left alone, otherwise it
+	 * is updated with a new object.
 	 */
-	if (dest_desc->common.type != (u8) destination_type) {
-		status = AE_AML_INTERNAL;
-		goto clean_up_and_bail_out;
+	status = acpi_aml_convert_to_target_type (target_type, &source_desc, walk_state);
+	if (ACPI_FAILURE (status)) {
+		return (status);
 	}
 
+
 	/*
-	 * Acpi_everything is ready to execute now, We have
-	 * a value we can handle, just perform the update
+	 * We now have two objects of identical types, and we can perform a
+	 * copy of the *value* of the source object.
 	 */
-
-	switch (destination_type)
+	switch (target_type)
 	{
-		/* Type of Name's existing value */
-
-	case INTERNAL_TYPE_BANK_FIELD:
-
-		/*
-		 * Get the global lock if needed
-		 */
-		locked = acpi_aml_acquire_global_lock (dest_desc->bank_field.lock_rule);
+	case ACPI_TYPE_ANY:
+	case INTERNAL_TYPE_DEF_ANY:
 
 		/*
-		 *  Set Bank value to select proper Bank
-		 *  Perform the update (Set Bank Select)
+		 * The target namespace node is uninitialized (has no target object),
+		 * and will take on the type of the source object
 		 */
 
-		status = acpi_aml_access_named_field (ACPI_WRITE,
-				 dest_desc->bank_field.bank_select,
-				 &dest_desc->bank_field.value,
-				 sizeof (dest_desc->bank_field.value));
-		if (ACPI_SUCCESS (status)) {
-			/* Set bank select successful, set data value  */
-
-			status = acpi_aml_access_named_field (ACPI_WRITE,
-					   dest_desc->bank_field.bank_select,
-					   &val_desc->bank_field.value,
-					   sizeof (val_desc->bank_field.value));
-		}
-
+		*target_desc_ptr = source_desc;
 		break;
 
 
-	case INTERNAL_TYPE_DEF_FIELD:
-
-		/*
-		 * Get the global lock if needed
-		 */
-		locked = acpi_aml_acquire_global_lock (val_desc->field.lock_rule);
+	case ACPI_TYPE_INTEGER:
 
-		/*
-		 *  Perform the update
-		 */
-
-		switch (val_desc->common.type)
-		{
-		case ACPI_TYPE_NUMBER:
-			buffer = (u8 *) &val_desc->number.value;
-			length = sizeof (val_desc->number.value);
-			break;
-
-		case ACPI_TYPE_BUFFER:
-			buffer = (u8 *) val_desc->buffer.pointer;
-			length = val_desc->buffer.length;
-			break;
-
-		case ACPI_TYPE_STRING:
-			buffer = (u8 *) val_desc->string.pointer;
-			length = val_desc->string.length;
-			break;
-		}
-
-		status = acpi_aml_access_named_field (ACPI_WRITE,
-				  node, buffer, length);
-
-		break;      /* Global Lock released below   */
-
-
-	case ACPI_TYPE_STRING:
+		target_desc->integer.value = source_desc->integer.value;
 
-		/*
-		 *  Perform the update
-		 */
-
-		switch (val_desc->common.type)
-		{
-		case ACPI_TYPE_NUMBER:
-			buffer = (u8 *) &val_desc->number.value;
-			length = sizeof (val_desc->number.value);
-			break;
-
-		case ACPI_TYPE_BUFFER:
-			buffer = (u8 *) val_desc->buffer.pointer;
-			length = val_desc->buffer.length;
-			break;
-
-		case ACPI_TYPE_STRING:
-			buffer = (u8 *) val_desc->string.pointer;
-			length = val_desc->string.length;
-			break;
-		}
-
-		/*
-		 *  Setting a string value replaces the old string
-		 */
-
-		if (length < dest_desc->string.length) {
-			/*
-			 *  Zero fill, not willing to do pointer arithmetic for
-			 *  archetecture independance.  Just clear the whole thing
-			 */
-			MEMSET(dest_desc->string.pointer, 0, dest_desc->string.length);
-			MEMCPY(dest_desc->string.pointer, buffer, length);
-		}
-		else {
-			/*
-			 *  Free the current buffer, then allocate a buffer
-			 *  large enough to hold the value
-			 */
-			if ( dest_desc->string.pointer &&
-				!acpi_tb_system_table_pointer (dest_desc->string.pointer))
-			{
-				/*
-				 *  Only free if not a pointer into the DSDT
-				 */
+		/* Truncate value if we are executing from a 32-bit ACPI table */
 
-				acpi_cm_free(dest_desc->string.pointer);
-			}
+		acpi_aml_truncate_for32bit_table (target_desc, walk_state);
+		break;
 
-			dest_desc->string.pointer = acpi_cm_allocate (length + 1);
-			dest_desc->string.length = length;
 
-			if (!dest_desc->string.pointer) {
-				status = AE_NO_MEMORY;
-				goto clean_up_and_bail_out;
-			}
+	case ACPI_TYPE_FIELD_UNIT:
 
-			MEMCPY(dest_desc->string.pointer, buffer, length);
-		}
+		status = acpi_aml_copy_integer_to_field_unit (source_desc, target_desc);
 		break;
 
 
-	case ACPI_TYPE_BUFFER:
-
-		/*
-		 *  Perform the update to the buffer
-		 */
-
-		switch (val_desc->common.type)
-		{
-		case ACPI_TYPE_NUMBER:
-			buffer = (u8 *) &val_desc->number.value;
-			length = sizeof (val_desc->number.value);
-			break;
-
-		case ACPI_TYPE_BUFFER:
-			buffer = (u8 *) val_desc->buffer.pointer;
-			length = val_desc->buffer.length;
-			break;
-
-		case ACPI_TYPE_STRING:
-			buffer = (u8 *) val_desc->string.pointer;
-			length = val_desc->string.length;
-			break;
-		}
+	case INTERNAL_TYPE_BANK_FIELD:
 
-		/*
-		 *  Buffer is a static allocation,
-		 *  only place what will fit in the buffer.
-		 */
-		if (length <= dest_desc->buffer.length) {
-			/*
-			 *  Zero fill first, not willing to do pointer arithmetic for
-			 *  archetecture independence.  Just clear the whole thing
-			 */
-			MEMSET(dest_desc->buffer.pointer, 0, dest_desc->buffer.length);
-			MEMCPY(dest_desc->buffer.pointer, buffer, length);
-		}
-		else {
-			/*
-			 *  truncate, copy only what will fit
-			 */
-			MEMCPY(dest_desc->buffer.pointer, buffer, dest_desc->buffer.length);
-		}
+		status = acpi_aml_copy_integer_to_bank_field (source_desc, target_desc);
 		break;
 
 
 	case INTERNAL_TYPE_INDEX_FIELD:
 
-		/*
-		 * Get the global lock if needed
-		 */
-		locked = acpi_aml_acquire_global_lock (dest_desc->index_field.lock_rule);
-
-		/*
-		 *  Set Index value to select proper Data register
-		 *  perform the update (Set index)
-		 */
-
-		status = acpi_aml_access_named_field (ACPI_WRITE,
-				 dest_desc->index_field.index,
-				 &dest_desc->index_field.value,
-				 sizeof (dest_desc->index_field.value));
-
-		if (ACPI_SUCCESS (status)) {
-			/* set index successful, next set Data value */
-
-			status = acpi_aml_access_named_field (ACPI_WRITE,
-					   dest_desc->index_field.data,
-					   &val_desc->number.value,
-					   sizeof (val_desc->number.value));
-		}
+		status = acpi_aml_copy_integer_to_index_field (source_desc, target_desc);
 		break;
 
 
-	case ACPI_TYPE_FIELD_UNIT:
-
-
-		/*
-		 * If the Field Buffer and Index have not been previously evaluated,
-		 * evaluate them and save the results.
-		 */
-		if (!(dest_desc->common.flags & AOPOBJ_DATA_VALID)) {
-			status = acpi_ds_get_field_unit_arguments (dest_desc);
-			if (ACPI_FAILURE (status)) {
-				return (status);
-			}
-		}
-
-		if ((!dest_desc->field_unit.container ||
-			ACPI_TYPE_BUFFER != dest_desc->field_unit.container->common.type))
-		{
-			status = AE_AML_INTERNAL;
-			goto clean_up_and_bail_out;
-		}
-
-		/*
-		 *  Get the global lock if needed
-		 */
-		locked = acpi_aml_acquire_global_lock (dest_desc->field_unit.lock_rule);
-
-		/*
-		 * TBD: [Unhandled] REMOVE this limitation
-		 * Make sure the operation is within the limits of our implementation
-		 * this is not a Spec limitation!!
-		 */
-		if (dest_desc->field_unit.length + dest_desc->field_unit.bit_offset > 32) {
-			status = AE_NOT_IMPLEMENTED;
-			goto clean_up_and_bail_out;
-		}
-
-		/* Field location is (base of buffer) + (byte offset) */
-
-		location = dest_desc->field_unit.container->buffer.pointer
-				  + dest_desc->field_unit.offset;
-
-		/*
-		 * Construct Mask with 1 bits where the field is,
-		 * 0 bits elsewhere
-		 */
-		mask = ((u32) 1 << dest_desc->field_unit.length) - ((u32)1
-				   << dest_desc->field_unit.bit_offset);
-
-		/* Zero out the field in the buffer */
-
-		MOVE_UNALIGNED32_TO_32 (&new_value, location);
-		new_value &= ~mask;
-
-		/*
-		 * Shift and mask the new value into position,
-		 * and or it into the buffer.
-		 */
-		new_value |= (val_desc->number.value << dest_desc->field_unit.bit_offset) &
-				 mask;
-
-		/* Store back the value */
-
-		MOVE_UNALIGNED32_TO_32 (location, &new_value);
+	case ACPI_TYPE_STRING:
 
+		status = acpi_aml_copy_string_to_string (source_desc, target_desc);
 		break;
 
 
-	case ACPI_TYPE_NUMBER:
-
-
-		dest_desc->number.value = val_desc->number.value;
-
-		/* Truncate value if we are executing from a 32-bit ACPI table */
+	case ACPI_TYPE_BUFFER:
 
-		acpi_aml_truncate_for32bit_table (dest_desc, walk_state);
+		status = acpi_aml_copy_buffer_to_buffer (source_desc, target_desc);
 		break;
 
 
 	case ACPI_TYPE_PACKAGE:
 
 		/*
-		 *  TBD: [Unhandled] Not real sure what to do here
+		 * TBD: [Unhandled] Not real sure what to do here
 		 */
 		status = AE_NOT_IMPLEMENTED;
 		break;
@@ -518,23 +249,12 @@
 	default:
 
 		/*
-		 * All other types than Alias and the various Fields come here.
-		 * Store Val_desc as the new value of the Name, and set
-		 * the Name's type to that of the value being stored in it.
-		 * Val_desc reference count is incremented by Attach_object.
+		 * All other types come here.
 		 */
-
 		status = AE_NOT_IMPLEMENTED;
 		break;
 	}
 
-
-clean_up_and_bail_out:
-
-	/*
-	 * Release global lock if we acquired it earlier
-	 */
-	acpi_aml_release_global_lock (locked);
 
 	return (status);
 }
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amstorob.c linux/drivers/acpi/interpreter/amstorob.c
--- v2.4.0/linux/drivers/acpi/interpreter/amstorob.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amstorob.c	Mon Jan 29 10:15:59 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amstorob - AML Interpreter object store support, store to object
- *              $Revision: 18 $
+ *              $Revision: 22 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -40,281 +40,383 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_aml_store_object_to_object
+ * FUNCTION:    Acpi_aml_copy_buffer_to_buffer
  *
- * PARAMETERS:  *Val_desc           - Value to be stored
- *              *Dest_desc          - Object to receive the value
+ * PARAMETERS:  Source_desc         - Source object to copy
+ *              Target_desc         - Destination object of the copy
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Store an object to another object.
+ * DESCRIPTION: Copy a buffer object to another buffer object.
  *
- *              The Assignment of an object to another (not named) object
- *              is handled here.
- *              The val passed in will replace the current value (if any)
- *              with the input value.
- *
- *              When storing into an object the data is converted to the
- *              target object type then stored in the object.  This means
- *              that the target object type (for an initialized target) will
- *              not be changed by a store operation.
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_copy_buffer_to_buffer (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc)
+{
+	u32                     length;
+	u8                      *buffer;
+
+ 	   /*
+	 * We know that Source_desc is a buffer by now
+	 */
+	buffer = (u8 *) source_desc->buffer.pointer;
+	length = source_desc->buffer.length;
+
+	/*
+	 * Buffer is a static allocation,
+	 * only place what will fit in the buffer.
+	 */
+	if (length <= target_desc->buffer.length) {
+		/* Clear existing buffer and copy in the new one */
+
+		MEMSET(target_desc->buffer.pointer, 0, target_desc->buffer.length);
+		MEMCPY(target_desc->buffer.pointer, buffer, length);
+	}
+
+	else {
+		/*
+		 * Truncate the source, copy only what will fit
+		 */
+		MEMCPY(target_desc->buffer.pointer, buffer, target_desc->buffer.length);
+
+	}
+
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_copy_string_to_string
+ *
+ * PARAMETERS:  Source_desc         - Source object to copy
+ *              Target_desc         - Destination object of the copy
+ *
+ * RETURN:      Status
  *
- *              This module allows destination types of Number, String,
- *              and Buffer.
+ * DESCRIPTION: Copy a String object to another String object
  *
  ******************************************************************************/
 
 ACPI_STATUS
-acpi_aml_store_object_to_object (
-	ACPI_OPERAND_OBJECT     *val_desc,
-	ACPI_OPERAND_OBJECT     *dest_desc,
-	ACPI_WALK_STATE         *walk_state)
+acpi_aml_copy_string_to_string (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc)
 {
-	ACPI_STATUS             status = AE_OK;
-	u8                      *buffer = NULL;
-	u32                     length = 0;
-	OBJECT_TYPE_INTERNAL    destination_type = dest_desc->common.type;
+	u32                     length;
+	u8                      *buffer;
 
 
 	/*
-	 *  Assuming the parameters are valid!!!
+	 * We know that Source_desc is a string by now.
 	 */
-	ACPI_ASSERT((dest_desc) && (val_desc));
+	buffer = (u8 *) source_desc->string.pointer;
+	length = source_desc->string.length;
 
 	/*
-	 *  First ensure we have a value that can be stored in the target
+	 * Setting a string value replaces the old string
 	 */
-	switch (destination_type)
-	{
-		/* Type of Name's existing value */
+	if (length < target_desc->string.length) {
+		/* Clear old string and copy in the new one */
 
-	case ACPI_TYPE_NUMBER:
+		MEMSET(target_desc->string.pointer, 0, target_desc->string.length);
+		MEMCPY(target_desc->string.pointer, buffer, length);
+	}
 
+	else {
 		/*
-		 *  These cases all require only number values or values that
-		 *  can be converted to numbers.
-		 *
-		 *  If value is not a Number, try to resolve it to one.
+		 * Free the current buffer, then allocate a buffer
+		 * large enough to hold the value
 		 */
-
-		if (val_desc->common.type != ACPI_TYPE_NUMBER) {
+		if (target_desc->string.pointer &&
+			!acpi_tb_system_table_pointer (target_desc->string.pointer))
+		{
 			/*
-			 *  Initially not a number, convert
+			 * Only free if not a pointer into the DSDT
 			 */
-			status = acpi_aml_resolve_to_value (&val_desc, walk_state);
-			if (ACPI_SUCCESS (status) &&
-				(val_desc->common.type != ACPI_TYPE_NUMBER))
-			{
-				/*
-				 *  Conversion successful but still not a number
-				 */
-				status = AE_AML_OPERAND_TYPE;
-			}
+			acpi_cm_free(target_desc->string.pointer);
 		}
 
-		break;
+		target_desc->string.pointer = acpi_cm_allocate (length + 1);
+		target_desc->string.length = length;
 
-	case ACPI_TYPE_STRING:
-	case ACPI_TYPE_BUFFER:
+		if (!target_desc->string.pointer) {
+			return (AE_NO_MEMORY);
+		}
 
-		/*
-		 *  Storing into a Field in a region or into a buffer or into
-		 *  a string all is essentially the same.
-		 *
-		 *  If value is not a valid type, try to resolve it to one.
-		 */
+		MEMCPY(target_desc->string.pointer, buffer, length);
+	}
 
-		if ((val_desc->common.type != ACPI_TYPE_NUMBER) &&
-			(val_desc->common.type != ACPI_TYPE_BUFFER) &&
-			(val_desc->common.type != ACPI_TYPE_STRING))
-		{
-			/*
-			 *  Initially not a valid type, convert
-			 */
-			status = acpi_aml_resolve_to_value (&val_desc, walk_state);
-			if (ACPI_SUCCESS (status) &&
-				(val_desc->common.type != ACPI_TYPE_NUMBER) &&
-				(val_desc->common.type != ACPI_TYPE_BUFFER) &&
-				(val_desc->common.type != ACPI_TYPE_STRING))
-			{
-				/*
-				 *  Conversion successful but still not a valid type
-				 */
-				status = AE_AML_OPERAND_TYPE;
-			}
-		}
-		break;
+	return (AE_OK);
+}
 
 
-	default:
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_copy_integer_to_index_field
+ *
+ * PARAMETERS:  Source_desc         - Source object to copy
+ *              Target_desc         - Destination object of the copy
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Write an Integer to an Index Field
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_copy_integer_to_index_field (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc)
+{
+	ACPI_STATUS             status;
+	u8                      locked;
+
+
+	/*
+	 * Get the global lock if needed
+	 */
+	locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule);
+
+	/*
+	 * Set Index value to select proper Data register
+	 * perform the update (Set index)
+	 */
+	status = acpi_aml_access_named_field (ACPI_WRITE,
+			 target_desc->index_field.index,
+			 &target_desc->index_field.value,
+			 sizeof (target_desc->index_field.value));
+	if (ACPI_SUCCESS (status)) {
+		/* Set_index was successful, next set Data value */
+
+		status = acpi_aml_access_named_field (ACPI_WRITE,
+				   target_desc->index_field.data,
+				   &source_desc->integer.value,
+				   sizeof (source_desc->integer.value));
 
-		/*
-		 * TBD: [Unhandled] What other combinations must be implemented?
-		 */
-		status = AE_NOT_IMPLEMENTED;
-		break;
 	}
 
-	/* Exit now if failure above */
 
-	if (ACPI_FAILURE (status)) {
-		goto clean_up_and_bail_out;
+
+	/*
+	 * Release global lock if we acquired it earlier
+	 */
+	acpi_aml_release_global_lock (locked);
+
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_copy_integer_to_bank_field
+ *
+ * PARAMETERS:  Source_desc         - Source object to copy
+ *              Target_desc         - Destination object of the copy
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Write an Integer to a Bank Field
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_copy_integer_to_bank_field (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc)
+{
+	ACPI_STATUS             status;
+	u8                      locked;
+
+
+	/*
+	 * Get the global lock if needed
+	 */
+	locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule);
+
+
+	/*
+	 * Set Bank value to select proper Bank
+	 * Perform the update (Set Bank Select)
+	 */
+
+	status = acpi_aml_access_named_field (ACPI_WRITE,
+			 target_desc->bank_field.bank_select,
+			 &target_desc->bank_field.value,
+			 sizeof (target_desc->bank_field.value));
+	if (ACPI_SUCCESS (status)) {
+		/* Set bank select successful, set data value  */
+
+		status = acpi_aml_access_named_field (ACPI_WRITE,
+				   target_desc->bank_field.bank_select,
+				   &source_desc->bank_field.value,
+				   sizeof (source_desc->bank_field.value));
 	}
 
+
+
 	/*
-	 * Acpi_everything is ready to execute now, We have
-	 * a value we can handle, just perform the update
+	 * Release global lock if we acquired it earlier
 	 */
+	acpi_aml_release_global_lock (locked);
 
-	switch (destination_type)
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_copy_data_to_named_field
+ *
+ * PARAMETERS:  Source_desc         - Source object to copy
+ *              Node                - Destination Namespace node
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Copy raw data to a Named Field.  No implicit conversion
+ *              is performed on the source object
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_copy_data_to_named_field (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_NAMESPACE_NODE     *node)
+{
+	ACPI_STATUS             status;
+	u8                      locked;
+	u32                     length;
+	u8                      *buffer;
+
+
+	/*
+	 * Named fields (Create_xxx_field) - We don't perform any conversions on the
+	 * source operand, just use the raw data
+	 */
+	switch (source_desc->common.type)
 	{
+	case ACPI_TYPE_INTEGER:
+		buffer = (u8 *) &source_desc->integer.value;
+		length = sizeof (source_desc->integer.value);
+		break;
+
+	case ACPI_TYPE_BUFFER:
+		buffer = (u8 *) source_desc->buffer.pointer;
+		length = source_desc->buffer.length;
+		break;
 
 	case ACPI_TYPE_STRING:
+		buffer = (u8 *) source_desc->string.pointer;
+		length = source_desc->string.length;
+		break;
 
-		/*
-		 *  Perform the update
-		 */
+	default:
+		return (AE_TYPE);
+	}
 
-		switch (val_desc->common.type)
-		{
-		case ACPI_TYPE_NUMBER:
-			buffer = (u8 *) &val_desc->number.value;
-			length = sizeof (val_desc->number.value);
-			break;
-
-		case ACPI_TYPE_BUFFER:
-			buffer = (u8 *) val_desc->buffer.pointer;
-			length = val_desc->buffer.length;
-			break;
-
-		case ACPI_TYPE_STRING:
-			buffer = (u8 *) val_desc->string.pointer;
-			length = val_desc->string.length;
-			break;
-		}
+	/*
+	 * Get the global lock if needed before the update
+	 * TBD: not needed!
+	 */
+	locked = acpi_aml_acquire_global_lock (source_desc->field.lock_rule);
 
-		/*
-		 *  Setting a string value replaces the old string
-		 */
+	status = acpi_aml_access_named_field (ACPI_WRITE,
+			  node, buffer, length);
 
-		if (length < dest_desc->string.length) {
-			/*
-			 *  Zero fill, not willing to do pointer arithmetic for
-			 *  architecture independence.  Just clear the whole thing
-			 */
-			MEMSET(dest_desc->string.pointer, 0, dest_desc->string.length);
-			MEMCPY(dest_desc->string.pointer, buffer, length);
-		}
-		else {
-			/*
-			 *  Free the current buffer, then allocate a buffer
-			 *  large enough to hold the value
-			 */
-			if ( dest_desc->string.pointer &&
-				!acpi_tb_system_table_pointer (dest_desc->string.pointer))
-			{
-				/*
-				 *  Only free if not a pointer into the DSDT
-				 */
-
-				acpi_cm_free(dest_desc->string.pointer);
-			}
-
-			dest_desc->string.pointer = acpi_cm_allocate (length + 1);
-			dest_desc->string.length = length;
-
-			if (!dest_desc->string.pointer) {
-				status = AE_NO_MEMORY;
-				goto clean_up_and_bail_out;
-			}
+	acpi_aml_release_global_lock (locked);
 
-			MEMCPY(dest_desc->string.pointer, buffer, length);
-		}
-		break;
+	return (status);
+}
 
 
-	case ACPI_TYPE_BUFFER:
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_copy_integer_to_field_unit
+ *
+ * PARAMETERS:  Source_desc         - Source object to copy
+ *              Target_desc         - Destination object of the copy
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Write an Integer to a Field Unit.
+ *
+ ******************************************************************************/
 
-		/*
-		 *  Perform the update to the buffer
-		 */
+ACPI_STATUS
+acpi_aml_copy_integer_to_field_unit (
+	ACPI_OPERAND_OBJECT     *source_desc,
+	ACPI_OPERAND_OBJECT     *target_desc)
+{
+	ACPI_STATUS             status = AE_OK;
+	u8                      *location = NULL;
+	u32                     mask;
+	u32                     new_value;
+	u8                      locked = FALSE;
 
-		switch (val_desc->common.type)
-		{
-		case ACPI_TYPE_NUMBER:
-			buffer = (u8 *) &val_desc->number.value;
-			length = sizeof (val_desc->number.value);
-			break;
-
-		case ACPI_TYPE_BUFFER:
-			buffer = (u8 *) val_desc->buffer.pointer;
-			length = val_desc->buffer.length;
-			break;
-
-		case ACPI_TYPE_STRING:
-			buffer = (u8 *) val_desc->string.pointer;
-			length = val_desc->string.length;
-			break;
-		}
 
-		/*
-		 * If the buffer is uninitialized,
-		 *  memory needs to be allocated for the copy.
-		 */
-		if(0 == dest_desc->buffer.length) {
-			dest_desc->buffer.pointer = acpi_cm_callocate(length);
-			dest_desc->buffer.length = length;
-
-			if (!dest_desc->buffer.pointer) {
-				status = AE_NO_MEMORY;
-				goto clean_up_and_bail_out;
-			}
+	/*
+	 * If the Field Buffer and Index have not been previously evaluated,
+	 * evaluate them and save the results.
+	 */
+	if (!(target_desc->common.flags & AOPOBJ_DATA_VALID)) {
+		status = acpi_ds_get_field_unit_arguments (target_desc);
+		if (ACPI_FAILURE (status)) {
+			return (status);
 		}
+	}
 
-		/*
-		 *  Buffer is a static allocation,
-		 *  only place what will fit in the buffer.
-		 */
-		if (length <= dest_desc->buffer.length) {
-			/*
-			 *  Zero fill first, not willing to do pointer arithmetic for
-			 *  architecture independence.  Just clear the whole thing
-			 */
-			MEMSET(dest_desc->buffer.pointer, 0, dest_desc->buffer.length);
-			MEMCPY(dest_desc->buffer.pointer, buffer, length);
-		}
-		else {
-			/*
-			 *  truncate, copy only what will fit
-			 */
-			MEMCPY(dest_desc->buffer.pointer, buffer, dest_desc->buffer.length);
-		}
-		break;
+	if ((!target_desc->field_unit.container ||
+		ACPI_TYPE_BUFFER != target_desc->field_unit.container->common.type))
+	{
+		return (AE_AML_INTERNAL);
+	}
 
-	case ACPI_TYPE_NUMBER:
+	/*
+	 * Get the global lock if needed
+	 */
+	locked = acpi_aml_acquire_global_lock (target_desc->field_unit.lock_rule);
 
-		dest_desc->number.value = val_desc->number.value;
+	/*
+	 * TBD: [Unhandled] REMOVE this limitation
+	 * Make sure the operation is within the limits of our implementation
+	 * this is not a Spec limitation!!
+	 */
+	if (target_desc->field_unit.length + target_desc->field_unit.bit_offset > 32) {
+		return (AE_NOT_IMPLEMENTED);
+	}
 
-		/* Truncate value if we are executing from a 32-bit ACPI table */
+	/* Field location is (base of buffer) + (byte offset) */
 
-		acpi_aml_truncate_for32bit_table (dest_desc, walk_state);
-		break;
+	location = target_desc->field_unit.container->buffer.pointer
+			  + target_desc->field_unit.offset;
 
-	default:
+	/*
+	 * Construct Mask with 1 bits where the field is,
+	 * 0 bits elsewhere
+	 */
+	mask = ((u32) 1 << target_desc->field_unit.length) - ((u32)1
+			   << target_desc->field_unit.bit_offset);
 
-		/*
-		 * All other types than Alias and the various Fields come here.
-		 * Store Val_desc as the new value of the Name, and set
-		 * the Name's type to that of the value being stored in it.
-		 * Val_desc reference count is incremented by Attach_object.
-		 */
+	/* Zero out the field in the buffer */
 
-		status = AE_NOT_IMPLEMENTED;
-		break;
-	}
+	MOVE_UNALIGNED32_TO_32 (&new_value, location);
+	new_value &= ~mask;
 
-clean_up_and_bail_out:
+	/*
+	 * Shift and mask the new value into position,
+	 * and or it into the buffer.
+	 */
+	new_value |= (source_desc->integer.value << target_desc->field_unit.bit_offset) &
+			 mask;
 
-	return (status);
+	/* Store back the value */
+
+	MOVE_UNALIGNED32_TO_32 (location, &new_value);
+
+	return (AE_OK);
 }
+
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amsystem.c linux/drivers/acpi/interpreter/amsystem.c
--- v2.4.0/linux/drivers/acpi/interpreter/amsystem.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amsystem.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amsystem - Interface to OS services
- *              $Revision: 52 $
+ *              $Revision: 54 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -202,7 +202,7 @@
 	}
 
 	status = acpi_aml_system_wait_semaphore (obj_desc->mutex.semaphore,
-			  (u32) time_desc->number.value);
+			  (u32) time_desc->integer.value);
 	return (status);
 }
 
@@ -299,7 +299,7 @@
 
 	if (obj_desc) {
 		status = acpi_aml_system_wait_semaphore (obj_desc->event.semaphore,
-				  (u32) time_desc->number.value);
+				  (u32) time_desc->integer.value);
 	}
 
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amutils.c linux/drivers/acpi/interpreter/amutils.c
--- v2.4.0/linux/drivers/acpi/interpreter/amutils.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/interpreter/amutils.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amutils - interpreter/scanner utilities
- *              $Revision: 66 $
+ *              $Revision: 68 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -46,14 +46,11 @@
 
 
 /* Used to traverse nested packages when copying*/
+/* TBD: This must be removed! */
 
 INTERNAL_PKG_SEARCH_INFO        copy_level[MAX_PACKAGE_DEPTH];
 
 
-static NATIVE_CHAR          hex[] =
-	{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-
-
 /*******************************************************************************
  *
  * FUNCTION:    Acpi_aml_enter_interpreter
@@ -156,7 +153,7 @@
 	 */
 
 	if ((!obj_desc) ||
-		(obj_desc->common.type != ACPI_TYPE_NUMBER) ||
+		(obj_desc->common.type != ACPI_TYPE_INTEGER) ||
 		(!walk_state->method_node))
 	{
 		return;
@@ -167,7 +164,7 @@
 		 * We are running a method that exists in a 32-bit ACPI table.
 		 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
 		 */
-		obj_desc->number.value &= (ACPI_INTEGER) ACPI_UINT32_MAX;
+		obj_desc->integer.value &= (ACPI_INTEGER) ACPI_UINT32_MAX;
 	}
 }
 
@@ -343,10 +340,10 @@
 	out_string[0] = (char) ('@' + ((id >> 26) & 0x1f));
 	out_string[1] = (char) ('@' + ((id >> 21) & 0x1f));
 	out_string[2] = (char) ('@' + ((id >> 16) & 0x1f));
-	out_string[3] = hex[(id >> 12) & 0xf];
-	out_string[4] = hex[(id >> 8) & 0xf];
-	out_string[5] = hex[(id >> 4) & 0xf];
-	out_string[6] = hex[id & 0xf];
+	out_string[3] = acpi_gbl_hex_to_ascii[(id >> 12) & 0xf];
+	out_string[4] = acpi_gbl_hex_to_ascii[(id >> 8) & 0xf];
+	out_string[5] = acpi_gbl_hex_to_ascii[(id >> 4) & 0xf];
+	out_string[6] = acpi_gbl_hex_to_ascii[id & 0xf];
 	out_string[7] = 0;
 
 	return (AE_OK);
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amxface.c linux/drivers/acpi/interpreter/amxface.c
--- v2.4.0/linux/drivers/acpi/interpreter/amxface.c	Fri Sep 15 14:30:30 2000
+++ linux/drivers/acpi/interpreter/amxface.c	Mon Jan 22 13:23:42 2001
@@ -2,12 +2,12 @@
 /******************************************************************************
  *
  * Module Name: amxface - External interpreter interfaces
- *              $Revision: 22 $
+ *              $Revision: 24 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/ksyms.c linux/drivers/acpi/ksyms.c
--- v2.4.0/linux/drivers/acpi/ksyms.c	Fri Dec 29 14:21:48 2000
+++ linux/drivers/acpi/ksyms.c	Wed Dec 31 16:00:00 1969
@@ -1,91 +0,0 @@
-/*
- *  ksyms.c - ACPI exported symbols
- *
- *  Copyright (C) 2000 Andrew Grover
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/acpi.h>
-#include "acpi.h"
-#include "acdebug.h"
-
-extern int acpi_in_debugger;
-
-#define _COMPONENT	OS_DEPENDENT
-	MODULE_NAME	("symbols")
-
-#ifdef ENABLE_DEBUGGER
-EXPORT_SYMBOL(acpi_in_debugger);
-EXPORT_SYMBOL(acpi_db_user_commands);
-#endif
-
-EXPORT_SYMBOL(acpi_os_free);
-EXPORT_SYMBOL(acpi_os_breakpoint);
-EXPORT_SYMBOL(acpi_os_printf);
-EXPORT_SYMBOL(acpi_os_callocate);
-EXPORT_SYMBOL(acpi_os_sleep);
-EXPORT_SYMBOL(acpi_os_sleep_usec);
-EXPORT_SYMBOL(acpi_os_in8);
-EXPORT_SYMBOL(acpi_os_out8);
-EXPORT_SYMBOL(acpi_os_queue_for_execution);
-
-EXPORT_SYMBOL(acpi_dbg_layer);
-EXPORT_SYMBOL(acpi_dbg_level);
-EXPORT_SYMBOL(function_exit);
-EXPORT_SYMBOL(function_trace);
-EXPORT_SYMBOL(function_status_exit);
-EXPORT_SYMBOL(function_value_exit);
-EXPORT_SYMBOL(debug_print_raw);
-EXPORT_SYMBOL(debug_print_prefix);
-
-EXPORT_SYMBOL(acpi_cm_strncmp);
-EXPORT_SYMBOL(acpi_cm_memcpy);
-EXPORT_SYMBOL(acpi_cm_memset);
-
-EXPORT_SYMBOL(acpi_get_handle);
-EXPORT_SYMBOL(acpi_get_parent);
-EXPORT_SYMBOL(acpi_get_type);
-EXPORT_SYMBOL(acpi_get_name);
-EXPORT_SYMBOL(acpi_get_object_info);
-EXPORT_SYMBOL(acpi_get_next_object);
-EXPORT_SYMBOL(acpi_evaluate_object);
-
-EXPORT_SYMBOL(acpi_install_notify_handler);
-EXPORT_SYMBOL(acpi_remove_notify_handler);
-EXPORT_SYMBOL(acpi_install_gpe_handler);
-EXPORT_SYMBOL(acpi_remove_gpe_handler);
-EXPORT_SYMBOL(acpi_install_address_space_handler);
-EXPORT_SYMBOL(acpi_remove_address_space_handler);
-
-EXPORT_SYMBOL(acpi_get_current_resources);
-EXPORT_SYMBOL(acpi_get_possible_resources);
-EXPORT_SYMBOL(acpi_set_current_resources);
-
-EXPORT_SYMBOL(acpi_enable_event);
-EXPORT_SYMBOL(acpi_disable_event);
-EXPORT_SYMBOL(acpi_clear_event);
-
-EXPORT_SYMBOL(acpi_get_processor_throttling_info);
-EXPORT_SYMBOL(acpi_get_processor_throttling_state);
-EXPORT_SYMBOL(acpi_set_processor_throttling_state);
-
-EXPORT_SYMBOL(acpi_get_processor_cx_info);
-EXPORT_SYMBOL(acpi_set_processor_sleep_state);
-EXPORT_SYMBOL(acpi_processor_sleep);
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nsaccess.c linux/drivers/acpi/namespace/nsaccess.c
--- v2.4.0/linux/drivers/acpi/namespace/nsaccess.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nsaccess.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
- *              $Revision: 117 $
+ *              $Revision: 119 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -117,9 +117,9 @@
 			switch (init_val->type)
 			{
 
-			case ACPI_TYPE_NUMBER:
+			case ACPI_TYPE_INTEGER:
 
-				obj_desc->number.value =
+				obj_desc->integer.value =
 						(ACPI_INTEGER) STRTOUL (init_val->val, NULL, 10);
 				break;
 
@@ -239,7 +239,7 @@
 	ACPI_NAMESPACE_NODE     **return_node)
 {
 	ACPI_STATUS             status;
-	ACPI_NAMESPACE_NODE      *prefix_node;
+	ACPI_NAMESPACE_NODE     *prefix_node;
 	ACPI_NAMESPACE_NODE     *current_node = NULL;
 	ACPI_NAMESPACE_NODE     *scope_to_push = NULL;
 	ACPI_NAMESPACE_NODE     *this_node = NULL;
@@ -248,8 +248,7 @@
 	u8                      null_name_path = FALSE;
 	OBJECT_TYPE_INTERNAL    type_to_check_for;
 	OBJECT_TYPE_INTERNAL    this_search_type;
-
-	DEBUG_ONLY_MEMBERS      (u32 i)
+	u32                     local_flags = flags & ~NS_ERROR_IF_FOUND;
 
 
 	if (!return_node) {
@@ -437,6 +436,7 @@
 		this_search_type = ACPI_TYPE_ANY;
 		if (!num_segments) {
 			this_search_type = type;
+			local_flags = flags;
 		}
 
 		/* Pluck one ACPI name from the front of the pathname */
@@ -447,7 +447,7 @@
 
 		status = acpi_ns_search_and_enter (simple_name, walk_state,
 				   current_node, interpreter_mode,
-				   this_search_type, flags,
+				   this_search_type, local_flags,
 				   &this_node);
 
 		if (ACPI_FAILURE (status)) {
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nsalloc.c linux/drivers/acpi/namespace/nsalloc.c
--- v2.4.0/linux/drivers/acpi/namespace/nsalloc.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nsalloc.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: nsalloc - Namespace allocation and deletion utilities
- *              $Revision: 43 $
+ *              $Revision: 45 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nseval.c linux/drivers/acpi/namespace/nseval.c
--- v2.4.0/linux/drivers/acpi/namespace/nseval.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nseval.c	Mon Jan 22 13:23:43 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: nseval - Object evaluation interfaces -- includes control
  *                       method lookup and execution.
- *              $Revision: 79 $
+ *              $Revision: 81 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nsinit.c linux/drivers/acpi/namespace/nsinit.c
--- v2.4.0/linux/drivers/acpi/namespace/nsinit.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nsinit.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: nsinit - namespace initialization
- *              $Revision: 9 $
+ *              $Revision: 12 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -239,7 +239,9 @@
 
 	status = acpi_cm_execute_STA (node, &flags);
 	if (ACPI_FAILURE (status)) {
-		return (status);
+		/* Ignore error and move on to next device */
+
+		return (AE_OK);
 	}
 
 	info->num_STA++;
@@ -260,12 +262,15 @@
 	}
 
 	else if (ACPI_FAILURE (status)) {
-		return (status);
+		/* Ignore error and move on to next device */
+
 	}
 
 	else {
+		/* Count of successfull INIs */
+
 		info->num_INI++;
 	}
 
-	return (status);
+	return (AE_OK);
 }
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nsload.c linux/drivers/acpi/namespace/nsload.c
--- v2.4.0/linux/drivers/acpi/namespace/nsload.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nsload.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: nsload - namespace loading/expanding/contracting procedures
- *              $Revision: 33 $
+ *              $Revision: 35 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nsnames.c linux/drivers/acpi/namespace/nsnames.c
--- v2.4.0/linux/drivers/acpi/namespace/nsnames.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nsnames.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: nsnames - Name manipulation and search
- *              $Revision: 51 $
+ *              $Revision: 53 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nsobject.c linux/drivers/acpi/namespace/nsobject.c
--- v2.4.0/linux/drivers/acpi/namespace/nsobject.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nsobject.c	Mon Jan 22 13:23:43 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: nsobject - Utilities for objects attached to namespace
  *                         table entries
- *              $Revision: 47 $
+ *              $Revision: 49 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -205,7 +205,7 @@
 			case AML_ZERO_OP: case AML_ONES_OP: case AML_ONE_OP:
 			case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP:
 
-				obj_type = ACPI_TYPE_NUMBER;
+				obj_type = ACPI_TYPE_INTEGER;
 				break;
 
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nssearch.c linux/drivers/acpi/namespace/nssearch.c
--- v2.4.0/linux/drivers/acpi/namespace/nssearch.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nssearch.c	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: nssearch - Namespace search
- *              $Revision: 62 $
+ *              $Revision: 64 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -68,8 +68,6 @@
 	ACPI_NAMESPACE_NODE     **return_node)
 {
 	ACPI_NAMESPACE_NODE     *next_node;
-
-
 
 
 	/*
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nsutils.c linux/drivers/acpi/namespace/nsutils.c
--- v2.4.0/linux/drivers/acpi/namespace/nsutils.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nsutils.c	Mon Jan 29 10:15:59 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
  *                        parents and siblings and Scope manipulation
- *              $Revision: 74 $
+ *              $Revision: 77 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nswalk.c linux/drivers/acpi/namespace/nswalk.c
--- v2.4.0/linux/drivers/acpi/namespace/nswalk.c	Fri Sep 15 14:30:30 2000
+++ linux/drivers/acpi/namespace/nswalk.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: nswalk - Functions for walking the APCI namespace
- *              $Revision: 17 $
+ *              $Revision: 19 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nsxfname.c linux/drivers/acpi/namespace/nsxfname.c
--- v2.4.0/linux/drivers/acpi/namespace/nsxfname.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/namespace/nsxfname.c	Mon Jan 22 13:23:43 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: nsxfname - Public interfaces to the ACPI subsystem
  *                         ACPI Namespace oriented interfaces
- *              $Revision: 73 $
+ *              $Revision: 75 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/namespace/nsxfobj.c linux/drivers/acpi/namespace/nsxfobj.c
--- v2.4.0/linux/drivers/acpi/namespace/nsxfobj.c	Mon Jan  1 10:23:21 2001
+++ linux/drivers/acpi/namespace/nsxfobj.c	Mon Jan 22 13:23:43 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: nsxfobj - Public interfaces to the ACPI subsystem
  *                         ACPI Object oriented interfaces
- *              $Revision: 75 $
+ *              $Revision: 78 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -695,4 +695,3 @@
 
 	return (status);
 }
-
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/os.c linux/drivers/acpi/os.c
--- v2.4.0/linux/drivers/acpi/os.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/os.c	Mon Jan 22 13:23:43 2001
@@ -24,8 +24,8 @@
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
+#include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/delay.h>
 #include "acpi.h"
 #include "driver.h"
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/parser/psargs.c linux/drivers/acpi/parser/psargs.c
--- v2.4.0/linux/drivers/acpi/parser/psargs.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/parser/psargs.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: psargs - Parse AML opcode arguments
- *              $Revision: 42 $
+ *              $Revision: 43 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/parser/psopcode.c linux/drivers/acpi/parser/psopcode.c
--- v2.4.0/linux/drivers/acpi/parser/psopcode.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/parser/psopcode.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: psopcode - Parser opcode information table
- *              $Revision: 24 $
+ *              $Revision: 27 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
 #define _PFX                        0x6D
 #define _UNKNOWN_OPCODE             0x02    /* An example unknown opcode */
 
-#define MAX_EXTENDED_OPCODE         0x87
+#define MAX_EXTENDED_OPCODE         0x88
 #define NUM_EXTENDED_OPCODE         MAX_EXTENDED_OPCODE + 1
 #define MAX_INTERNAL_OPCODE
 #define NUM_INTERNAL_OPCODE         MAX_INTERNAL_OPCODE + 1
@@ -83,9 +83,11 @@
 #define ARGP_WORD_OP                    ARGP_LIST1 (ARGP_WORDDATA)
 #define ARGP_DWORD_OP                   ARGP_LIST1 (ARGP_DWORDDATA)
 #define ARGP_STRING_OP                  ARGP_LIST1 (ARGP_CHARLIST)
+#define ARGP_QWORD_OP                   ARGP_LIST1 (ARGP_QWORDDATA)
 #define ARGP_SCOPE_OP                   ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_NAME,          ARGP_TERMLIST)
 #define ARGP_BUFFER_OP                  ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_TERMARG,       ARGP_BYTELIST)
 #define ARGP_PACKAGE_OP                 ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_BYTEDATA,      ARGP_DATAOBJLIST)
+#define ARGP_VAR_PACKAGE_OP             ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_BYTEDATA,      ARGP_DATAOBJLIST)
 #define ARGP_METHOD_OP                  ARGP_LIST4 (ARGP_PKGLENGTH,  ARGP_NAME,          ARGP_BYTEDATA,      ARGP_TERMLIST)
 #define ARGP_LOCAL0                     ARG_NONE
 #define ARGP_LOCAL1                     ARG_NONE
@@ -122,6 +124,8 @@
 #define ARGP_FIND_SET_LEFT_BIT_OP       ARGP_LIST2 (ARGP_TERMARG,    ARGP_TARGET)
 #define ARGP_FIND_SET_RIGHT_BIT_OP      ARGP_LIST2 (ARGP_TERMARG,    ARGP_TARGET)
 #define ARGP_DEREF_OF_OP                ARGP_LIST1 (ARGP_TERMARG)
+#define ARGP_CONCAT_RES_OP              ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
+#define ARGP_MOD_OP                     ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
 #define ARGP_NOTIFY_OP                  ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_TERMARG)
 #define ARGP_SIZE_OF_OP                 ARGP_LIST1 (ARGP_SUPERNAME)
 #define ARGP_INDEX_OP                   ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
@@ -131,12 +135,21 @@
 #define ARGP_BYTE_FIELD_OP              ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_NAME)
 #define ARGP_BIT_FIELD_OP               ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_NAME)
 #define ARGP_TYPE_OP                    ARGP_LIST1 (ARGP_SUPERNAME)
+#define ARGP_QWORD_FIELD_OP             ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_NAME)
 #define ARGP_LAND_OP                    ARGP_LIST2 (ARGP_TERMARG,    ARGP_TERMARG)
 #define ARGP_LOR_OP                     ARGP_LIST2 (ARGP_TERMARG,    ARGP_TERMARG)
 #define ARGP_LNOT_OP                    ARGP_LIST1 (ARGP_TERMARG)
 #define ARGP_LEQUAL_OP                  ARGP_LIST2 (ARGP_TERMARG,    ARGP_TERMARG)
 #define ARGP_LGREATER_OP                ARGP_LIST2 (ARGP_TERMARG,    ARGP_TERMARG)
 #define ARGP_LLESS_OP                   ARGP_LIST2 (ARGP_TERMARG,    ARGP_TERMARG)
+#define ARGP_TO_BUFFER_OP               ARGP_LIST2 (ARGP_TERMARG,    ARGP_TARGET)
+#define ARGP_TO_DEC_STR_OP              ARGP_LIST2 (ARGP_TERMARG,    ARGP_TARGET)
+#define ARGP_TO_HEX_STR_OP              ARGP_LIST2 (ARGP_TERMARG,    ARGP_TARGET)
+#define ARGP_TO_INTEGER_OP              ARGP_LIST2 (ARGP_TERMARG,    ARGP_TARGET)
+#define ARGP_TO_STRING_OP               ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
+#define ARGP_COPY_OP                    ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_SIMPLENAME)
+#define ARGP_MID_OP                     ARGP_LIST4 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TERMARG,   ARGP_TARGET)
+#define ARGP_CONTINUE_OP                ARG_NONE
 #define ARGP_IF_OP                      ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_TERMARG, ARGP_TERMLIST)
 #define ARGP_ELSE_OP                    ARGP_LIST2 (ARGP_PKGLENGTH,  ARGP_TERMLIST)
 #define ARGP_WHILE_OP                   ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_TERMARG, ARGP_TERMLIST)
@@ -149,6 +162,7 @@
 #define ARGP_EVENT_OP                   ARGP_LIST1 (ARGP_NAME)
 #define ARGP_COND_REF_OF_OP             ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_SUPERNAME)
 #define ARGP_CREATE_FIELD_OP            ARGP_LIST4 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TERMARG,   ARGP_NAME)
+#define ARGP_LOAD_TABLE_OP              ARGP_LIST6 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TERMARG,   ARGP_TERMARG,  ARGP_TERMARG,   ARGP_TERMARG)
 #define ARGP_LOAD_OP                    ARGP_LIST2 (ARGP_NAMESTRING, ARGP_SUPERNAME)
 #define ARGP_STALL_OP                   ARGP_LIST1 (ARGP_TERMARG)
 #define ARGP_SLEEP_OP                   ARGP_LIST1 (ARGP_TERMARG)
@@ -171,6 +185,7 @@
 #define ARGP_THERMAL_ZONE_OP            ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_NAME,          ARGP_OBJLIST)
 #define ARGP_INDEX_FIELD_OP             ARGP_LIST5 (ARGP_PKGLENGTH,  ARGP_NAMESTRING,    ARGP_NAMESTRING,ARGP_BYTEDATA,  ARGP_FIELDLIST)
 #define ARGP_BANK_FIELD_OP              ARGP_LIST6 (ARGP_PKGLENGTH,  ARGP_NAMESTRING,    ARGP_NAMESTRING,ARGP_TERMARG,   ARGP_BYTEDATA,  ARGP_FIELDLIST)
+#define ARGP_DATA_REGION_OP             ARGP_LIST4 (ARGP_NAMESTRING, ARGP_TERMARG,       ARGP_TERMARG,   ARGP_TERMARG)
 #define ARGP_LNOTEQUAL_OP               ARGP_LIST2 (ARGP_TERMARG,    ARGP_TERMARG)
 #define ARGP_LLESSEQUAL_OP              ARGP_LIST2 (ARGP_TERMARG,    ARGP_TERMARG)
 #define ARGP_LGREATEREQUAL_OP           ARGP_LIST2 (ARGP_TERMARG,    ARGP_TERMARG)
@@ -187,7 +202,7 @@
  * All AML opcodes and the runtime arguments for each.  Used by the AML interpreter  Each list is compressed
  * into a 32-bit number and stored in the master opcode table at the end of this file.
  *
- * (Used by Acpi_aml_prep_operands procedure)
+ * (Used by Acpi_aml_prep_operands procedure and the ASL Compiler)
  */
 
 #define ARGI_ZERO_OP                    ARG_NONE
@@ -198,9 +213,11 @@
 #define ARGI_WORD_OP                    ARGI_INVALID_OPCODE
 #define ARGI_DWORD_OP                   ARGI_INVALID_OPCODE
 #define ARGI_STRING_OP                  ARGI_INVALID_OPCODE
+#define ARGI_QWORD_OP                   ARGI_INVALID_OPCODE
 #define ARGI_SCOPE_OP                   ARGI_INVALID_OPCODE
 #define ARGI_BUFFER_OP                  ARGI_INVALID_OPCODE
 #define ARGI_PACKAGE_OP                 ARGI_INVALID_OPCODE
+#define ARGI_VAR_PACKAGE_OP             ARGI_INVALID_OPCODE
 #define ARGI_METHOD_OP                  ARGI_INVALID_OPCODE
 #define ARGI_LOCAL0                     ARG_NONE
 #define ARGI_LOCAL1                     ARG_NONE
@@ -218,40 +235,51 @@
 #define ARGI_ARG5                       ARG_NONE
 #define ARGI_ARG6                       ARG_NONE
 #define ARGI_STORE_OP                   ARGI_LIST2 (ARGI_ANYTYPE,    ARGI_TARGETREF)
-#define ARGI_REF_OF_OP                  ARGI_LIST1 (ARGI_REFERENCE)
-#define ARGI_ADD_OP                     ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_CONCAT_OP                  ARGI_LIST3 (ARGI_STRING,     ARGI_STRING,        ARGI_TARGETREF)
-#define ARGI_SUBTRACT_OP                ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_INCREMENT_OP               ARGI_LIST1 (ARGI_REFERENCE)
-#define ARGI_DECREMENT_OP               ARGI_LIST1 (ARGI_REFERENCE)
-#define ARGI_MULTIPLY_OP                ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_DIVIDE_OP                  ARGI_LIST4 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF,    ARGI_TARGETREF)
-#define ARGI_SHIFT_LEFT_OP              ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_SHIFT_RIGHT_OP             ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_BIT_AND_OP                 ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_BIT_NAND_OP                ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_BIT_OR_OP                  ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_BIT_NOR_OP                 ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_BIT_XOR_OP                 ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_BIT_NOT_OP                 ARGI_LIST2 (ARGI_NUMBER,     ARGI_TARGETREF)
-#define ARGI_FIND_SET_LEFT_BIT_OP       ARGI_LIST2 (ARGI_NUMBER,     ARGI_TARGETREF)
-#define ARGI_FIND_SET_RIGHT_BIT_OP      ARGI_LIST2 (ARGI_NUMBER,     ARGI_TARGETREF)
+#define ARGI_REF_OF_OP                  ARGI_LIST1 (ARGI_OBJECT_REF)
+#define ARGI_ADD_OP                     ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_CONCAT_OP                  ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA,   ARGI_TARGETREF)
+#define ARGI_SUBTRACT_OP                ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_INCREMENT_OP               ARGI_LIST1 (ARGI_INTEGER_REF)
+#define ARGI_DECREMENT_OP               ARGI_LIST1 (ARGI_INTEGER_REF)
+#define ARGI_MULTIPLY_OP                ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_DIVIDE_OP                  ARGI_LIST4 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF,    ARGI_TARGETREF)
+#define ARGI_SHIFT_LEFT_OP              ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_SHIFT_RIGHT_OP             ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_BIT_AND_OP                 ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_BIT_NAND_OP                ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_BIT_OR_OP                  ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_BIT_NOR_OP                 ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_BIT_XOR_OP                 ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_BIT_NOT_OP                 ARGI_LIST2 (ARGI_INTEGER,    ARGI_TARGETREF)
+#define ARGI_FIND_SET_LEFT_BIT_OP       ARGI_LIST2 (ARGI_INTEGER,    ARGI_TARGETREF)
+#define ARGI_FIND_SET_RIGHT_BIT_OP      ARGI_LIST2 (ARGI_INTEGER,    ARGI_TARGETREF)
 #define ARGI_DEREF_OF_OP                ARGI_LIST1 (ARGI_REFERENCE)
-#define ARGI_NOTIFY_OP                  ARGI_LIST2 (ARGI_REFERENCE,  ARGI_NUMBER)
+#define ARGI_CONCAT_RES_OP              ARGI_LIST3 (ARGI_BUFFER,     ARGI_BUFFER,        ARGI_TARGETREF)
+#define ARGI_MOD_OP                     ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_NOTIFY_OP                  ARGI_LIST2 (ARGI_DEVICE_REF, ARGI_INTEGER)
 #define ARGI_SIZE_OF_OP                 ARGI_LIST1 (ARGI_DATAOBJECT)
-#define ARGI_INDEX_OP                   ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_NUMBER,        ARGI_TARGETREF)
-#define ARGI_MATCH_OP                   ARGI_LIST6 (ARGI_PACKAGE,    ARGI_NUMBER,        ARGI_NUMBER,       ARGI_NUMBER,    ARGI_NUMBER,    ARGI_NUMBER)
-#define ARGI_DWORD_FIELD_OP             ARGI_LIST3 (ARGI_BUFFER,     ARGI_NUMBER,        ARGI_REFERENCE)
-#define ARGI_WORD_FIELD_OP              ARGI_LIST3 (ARGI_BUFFER,     ARGI_NUMBER,        ARGI_REFERENCE)
-#define ARGI_BYTE_FIELD_OP              ARGI_LIST3 (ARGI_BUFFER,     ARGI_NUMBER,        ARGI_REFERENCE)
-#define ARGI_BIT_FIELD_OP               ARGI_LIST3 (ARGI_BUFFER,     ARGI_NUMBER,        ARGI_REFERENCE)
+#define ARGI_INDEX_OP                   ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER,       ARGI_TARGETREF)
+#define ARGI_MATCH_OP                   ARGI_LIST6 (ARGI_PACKAGE,    ARGI_INTEGER,       ARGI_INTEGER,      ARGI_INTEGER,   ARGI_INTEGER,   ARGI_INTEGER)
+#define ARGI_DWORD_FIELD_OP             ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
+#define ARGI_WORD_FIELD_OP              ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
+#define ARGI_BYTE_FIELD_OP              ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
+#define ARGI_BIT_FIELD_OP               ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
 #define ARGI_TYPE_OP                    ARGI_LIST1 (ARGI_ANYTYPE)
-#define ARGI_LAND_OP                    ARGI_LIST2 (ARGI_NUMBER,     ARGI_NUMBER)
-#define ARGI_LOR_OP                     ARGI_LIST2 (ARGI_NUMBER,     ARGI_NUMBER)
-#define ARGI_LNOT_OP                    ARGI_LIST1 (ARGI_NUMBER)
-#define ARGI_LEQUAL_OP                  ARGI_LIST2 (ARGI_NUMBER,     ARGI_NUMBER)
-#define ARGI_LGREATER_OP                ARGI_LIST2 (ARGI_NUMBER,     ARGI_NUMBER)
-#define ARGI_LLESS_OP                   ARGI_LIST2 (ARGI_NUMBER,     ARGI_NUMBER)
+#define ARGI_QWORD_FIELD_OP             ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
+#define ARGI_LAND_OP                    ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LOR_OP                     ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LNOT_OP                    ARGI_LIST1 (ARGI_INTEGER)
+#define ARGI_LEQUAL_OP                  ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LGREATER_OP                ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LLESS_OP                   ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_TO_BUFFER_OP               ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
+#define ARGI_TO_DEC_STR_OP              ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
+#define ARGI_TO_HEX_STR_OP              ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
+#define ARGI_TO_INTEGER_OP              ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
+#define ARGI_TO_STRING_OP               ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_FIXED_TARGET)
+#define ARGI_COPY_OP                    ARGI_LIST2 (ARGI_ANYTYPE,    ARGI_SIMPLE_TARGET)
+#define ARGI_MID_OP                     ARGI_LIST4 (ARGI_BUFFERSTRING,ARGI_INTEGER,      ARGI_INTEGER,      ARGI_TARGETREF)
+#define ARGI_CONTINUE_OP                ARGI_INVALID_OPCODE
 #define ARGI_IF_OP                      ARGI_INVALID_OPCODE
 #define ARGI_ELSE_OP                    ARGI_INVALID_OPCODE
 #define ARGI_WHILE_OP                   ARGI_INVALID_OPCODE
@@ -262,23 +290,24 @@
 #define ARGI_ONES_OP                    ARG_NONE
 #define ARGI_MUTEX_OP                   ARGI_INVALID_OPCODE
 #define ARGI_EVENT_OP                   ARGI_INVALID_OPCODE
-#define ARGI_COND_REF_OF_OP             ARGI_LIST2 (ARGI_REFERENCE,  ARGI_TARGETREF)
-#define ARGI_CREATE_FIELD_OP            ARGI_LIST4 (ARGI_BUFFER,     ARGI_NUMBER,        ARGI_NUMBER,       ARGI_REFERENCE)
+#define ARGI_COND_REF_OF_OP             ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
+#define ARGI_CREATE_FIELD_OP            ARGI_LIST4 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_INTEGER,      ARGI_REFERENCE)
+#define ARGI_LOAD_TABLE_OP              ARGI_LIST6 (ARGI_STRING,     ARGI_STRING,        ARGI_STRING,       ARGI_STRING,    ARGI_STRING, ARGI_TARGETREF)
 #define ARGI_LOAD_OP                    ARGI_LIST2 (ARGI_REGION,     ARGI_TARGETREF)
-#define ARGI_STALL_OP                   ARGI_LIST1 (ARGI_NUMBER)
-#define ARGI_SLEEP_OP                   ARGI_LIST1 (ARGI_NUMBER)
-#define ARGI_ACQUIRE_OP                 ARGI_LIST2 (ARGI_MUTEX,      ARGI_NUMBER)
+#define ARGI_STALL_OP                   ARGI_LIST1 (ARGI_INTEGER)
+#define ARGI_SLEEP_OP                   ARGI_LIST1 (ARGI_INTEGER)
+#define ARGI_ACQUIRE_OP                 ARGI_LIST2 (ARGI_MUTEX,      ARGI_INTEGER)
 #define ARGI_SIGNAL_OP                  ARGI_LIST1 (ARGI_EVENT)
-#define ARGI_WAIT_OP                    ARGI_LIST2 (ARGI_EVENT,      ARGI_NUMBER)
+#define ARGI_WAIT_OP                    ARGI_LIST2 (ARGI_EVENT,      ARGI_INTEGER)
 #define ARGI_RESET_OP                   ARGI_LIST1 (ARGI_EVENT)
 #define ARGI_RELEASE_OP                 ARGI_LIST1 (ARGI_MUTEX)
-#define ARGI_FROM_BCD_OP                ARGI_LIST2 (ARGI_NUMBER,     ARGI_TARGETREF)
-#define ARGI_TO_BCD_OP                  ARGI_LIST2 (ARGI_NUMBER,     ARGI_TARGETREF)
+#define ARGI_FROM_BCD_OP                ARGI_LIST2 (ARGI_INTEGER,    ARGI_TARGETREF)
+#define ARGI_TO_BCD_OP                  ARGI_LIST2 (ARGI_INTEGER,    ARGI_FIXED_TARGET)
 #define ARGI_UNLOAD_OP                  ARGI_LIST1 (ARGI_DDBHANDLE)
 #define ARGI_REVISION_OP                ARG_NONE
 #define ARGI_DEBUG_OP                   ARG_NONE
-#define ARGI_FATAL_OP                   ARGI_LIST3 (ARGI_NUMBER,     ARGI_NUMBER,        ARGI_NUMBER)
-#define ARGI_REGION_OP                  ARGI_LIST2 (ARGI_NUMBER,     ARGI_NUMBER)
+#define ARGI_FATAL_OP                   ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_INTEGER)
+#define ARGI_REGION_OP                  ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
 #define ARGI_DEF_FIELD_OP               ARGI_INVALID_OPCODE
 #define ARGI_DEVICE_OP                  ARGI_INVALID_OPCODE
 #define ARGI_PROCESSOR_OP               ARGI_INVALID_OPCODE
@@ -286,6 +315,7 @@
 #define ARGI_THERMAL_ZONE_OP            ARGI_INVALID_OPCODE
 #define ARGI_INDEX_FIELD_OP             ARGI_INVALID_OPCODE
 #define ARGI_BANK_FIELD_OP              ARGI_INVALID_OPCODE
+#define ARGI_DATA_REGION_OP             ARGI_LIST3 (ARGI_STRING,     ARGI_STRING,       ARGI_STRING)
 #define ARGI_LNOTEQUAL_OP               ARGI_INVALID_OPCODE
 #define ARGI_LLESSEQUAL_OP              ARGI_INVALID_OPCODE
 #define ARGI_LGREATEREQUAL_OP           ARGI_INVALID_OPCODE
@@ -307,8 +337,8 @@
 {
 /* Index          Opcode                                   Type                   Class                 Has Arguments?   Name                 Parser Args             Interpreter Args */
 
-/*  00 */   /* AML_ZERO_OP */               OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT|        AML_NO_ARGS,  "Zero_op",            ARGP_ZERO_OP,           ARGI_ZERO_OP),
-/*  01 */   /* AML_ONE_OP */                OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT|        AML_NO_ARGS,  "One_op",             ARGP_ONE_OP,            ARGI_ONE_OP),
+/*  00 */   /* AML_ZERO_OP */               OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT|        AML_NO_ARGS,  "Zero",               ARGP_ZERO_OP,           ARGI_ZERO_OP),
+/*  01 */   /* AML_ONE_OP */                OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT|        AML_NO_ARGS,  "One",                ARGP_ONE_OP,            ARGI_ONE_OP),
 /*  02 */   /* AML_ALIAS_OP */              OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Alias",              ARGP_ALIAS_OP,          ARGI_ALIAS_OP),
 /*  03 */   /* AML_NAME_OP */               OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Name",               ARGP_NAME_OP,           ARGI_NAME_OP),
 /*  04 */   /* AML_BYTE_OP */               OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL|         AML_NO_ARGS,  "Byte_const",         ARGP_BYTE_OP,           ARGI_BYTE_OP),
@@ -337,7 +367,7 @@
 /*  1_b */  /* AML_STORE_OP */              OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "Store",              ARGP_STORE_OP,          ARGI_STORE_OP),
 /*  1_c */  /* AML_REF_OF_OP */             OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2|        AML_HAS_ARGS, "Ref_of",             ARGP_REF_OF_OP,         ARGI_REF_OF_OP),
 /*  1_d */  /* AML_ADD_OP */                OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r|       AML_HAS_ARGS, "Add",                ARGP_ADD_OP,            ARGI_ADD_OP),
-/*  1_e */  /* AML_CONCAT_OP */             OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r|       AML_HAS_ARGS, "Concat",             ARGP_CONCAT_OP,         ARGI_CONCAT_OP),
+/*  1_e */  /* AML_CONCAT_OP */             OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r|       AML_HAS_ARGS, "Concatenate",        ARGP_CONCAT_OP,         ARGI_CONCAT_OP),
 /*  1_f */  /* AML_SUBTRACT_OP */           OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r|       AML_HAS_ARGS, "Subtract",           ARGP_SUBTRACT_OP,       ARGI_SUBTRACT_OP),
 /*  20 */   /* AML_INCREMENT_OP */          OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2|        AML_HAS_ARGS, "Increment",          ARGP_INCREMENT_OP,      ARGI_INCREMENT_OP),
 /*  21 */   /* AML_DECREMENT_OP */          OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2|        AML_HAS_ARGS, "Decrement",          ARGP_DECREMENT_OP,      ARGI_DECREMENT_OP),
@@ -376,7 +406,7 @@
 /*  42 */   /* AML_RETURN_OP */             OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL|         AML_HAS_ARGS, "Return",             ARGP_RETURN_OP,         ARGI_RETURN_OP),
 /*  43 */   /* AML_BREAK_OP */              OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL|         AML_NO_ARGS,  "Break",              ARGP_BREAK_OP,          ARGI_BREAK_OP),
 /*  44 */   /* AML_BREAK_POINT_OP */        OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL|         AML_NO_ARGS,  "Break_point",        ARGP_BREAK_POINT_OP,    ARGI_BREAK_POINT_OP),
-/*  45 */   /* AML_ONES_OP */               OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT|        AML_NO_ARGS,  "Ones_op",            ARGP_ONES_OP,           ARGI_ONES_OP),
+/*  45 */   /* AML_ONES_OP */               OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT|        AML_NO_ARGS,  "Ones",               ARGP_ONES_OP,           ARGI_ONES_OP),
 
 /* Prefixed opcodes (Two-byte opcodes with a prefix op) */
 
@@ -402,7 +432,7 @@
 /*  59 */   /* AML_DEF_FIELD_OP */          OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Field",              ARGP_DEF_FIELD_OP,      ARGI_DEF_FIELD_OP),
 /*  5_a */  /* AML_DEVICE_OP */             OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Device",             ARGP_DEVICE_OP,         ARGI_DEVICE_OP),
 /*  5_b */  /* AML_PROCESSOR_OP */          OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Processor",          ARGP_PROCESSOR_OP,      ARGI_PROCESSOR_OP),
-/*  5_c */  /* AML_POWER_RES_OP */          OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Power_res",          ARGP_POWER_RES_OP,      ARGI_POWER_RES_OP),
+/*  5_c */  /* AML_POWER_RES_OP */          OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Power_resource",     ARGP_POWER_RES_OP,      ARGI_POWER_RES_OP),
 /*  5_d */  /* AML_THERMAL_ZONE_OP */       OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Thermal_zone",       ARGP_THERMAL_ZONE_OP,   ARGI_THERMAL_ZONE_OP),
 /*  5_e */  /* AML_INDEX_FIELD_OP */        OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Index_field",        ARGP_INDEX_FIELD_OP,    ARGI_INDEX_FIELD_OP),
 /*  5_f */  /* AML_BANK_FIELD_OP */         OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT|    AML_HAS_ARGS, "Bank_field",         ARGP_BANK_FIELD_OP,     ARGI_BANK_FIELD_OP),
@@ -423,6 +453,26 @@
 /*  6_b */  /* UNKNOWN OPCODES */           OP_INFO_ENTRY (ACPI_OP_TYPE_UNKNOWN | OPTYPE_BOGUS|          AML_HAS_ARGS, "UNKNOWN_OP!",        ARG_NONE,               ARG_NONE),
 /*  6_c */  /* ASCII CHARACTERS */          OP_INFO_ENTRY (ACPI_OP_TYPE_ASCII  | OPTYPE_BOGUS|           AML_HAS_ARGS, "ASCII_ONLY!",        ARG_NONE,               ARG_NONE),
 /*  6_d */  /* PREFIX CHARACTERS */         OP_INFO_ENTRY (ACPI_OP_TYPE_PREFIX | OPTYPE_BOGUS|           AML_HAS_ARGS, "PREFIX_ONLY!",       ARG_NONE,               ARG_NONE),
+
+
+/* ACPI 2.0 (new) opcodes */
+
+/*  6_e */  /* AML_QWORD_OP */              OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL|         AML_NO_ARGS,  "Qword_const",        ARGP_QWORD_OP,          ARGI_QWORD_OP),
+/*  6_f */  /* AML_VAR_PACKAGE_OP */        OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM|       AML_HAS_ARGS, "Var_package",        ARGP_VAR_PACKAGE_OP,    ARGI_VAR_PACKAGE_OP),
+/*  70 */   /* AML_CONCAT_RES_OP */         OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r|       AML_HAS_ARGS, "Concat_res",         ARGP_CONCAT_RES_OP,     ARGI_CONCAT_RES_OP),
+/*  71 */   /* AML_MOD_OP */                OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r|       AML_HAS_ARGS, "Mod",                ARGP_MOD_OP,            ARGI_MOD_OP),
+/*  72 */   /* AML_QWORD_FIELD_OP */        OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD|    AML_HAS_ARGS, "Create_qWord_field", ARGP_QWORD_FIELD_OP,    ARGI_QWORD_FIELD_OP),
+/*  73 */   /* AML_TO_BUFFER_OP */          OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "To_buffer",          ARGP_TO_BUFFER_OP,      ARGI_TO_BUFFER_OP),
+/*  74 */   /* AML_TO_DEC_STR_OP */         OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "To_dec_string",      ARGP_TO_DEC_STR_OP,     ARGI_TO_DEC_STR_OP),
+/*  75 */   /* AML_TO_HEX_STR_OP */         OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "To_hex_string",      ARGP_TO_HEX_STR_OP,     ARGI_TO_HEX_STR_OP),
+/*  76 */   /* AML_TO_INTEGER_OP */         OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "To_integer",         ARGP_TO_INTEGER_OP,     ARGI_TO_INTEGER_OP),
+/*  77 */   /* AML_TO_STRING_OP */          OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "To_string",          ARGP_TO_STRING_OP,      ARGI_TO_STRING_OP),
+/*  78 */   /* AML_COPY_OP */               OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "Copy",               ARGP_COPY_OP,           ARGI_COPY_OP),
+/*  79 */   /* AML_MID_OP */                OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "Mid",                ARGP_MID_OP,            ARGI_MID_OP),
+/*  7_a */  /* AML_CONTINUE_OP */           OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL|         AML_NO_ARGS,  "Continue",           ARGP_CONTINUE_OP,       ARGI_CONTINUE_OP),
+/*  7_b */  /* AML_LOAD_TABLE_OP */         OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "Load_table",         ARGP_LOAD_TABLE_OP,     ARGI_LOAD_TABLE_OP),
+/*  7_c */  /* AML_DATA_REGION_OP */        OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r|      AML_HAS_ARGS, "Data_op_region",     ARGP_DATA_REGION_OP,    ARGI_DATA_REGION_OP),
+
 };
 
 /*
@@ -433,9 +483,10 @@
 static u8 aml_short_op_info_index[256] =
 {
 /*              0     1     2     3     4     5     6     7  */
+/*              8     9     A     B     C     D     E     F  */
 /* 0x00 */    0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
-/* 0x08 */    0x03, _UNK, 0x04, 0x05, 0x06, 0x07, _UNK, _UNK,
-/* 0x10 */    0x08, 0x09, 0x0a, _UNK, 0x0b, _UNK, _UNK, _UNK,
+/* 0x08 */    0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
+/* 0x10 */    0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
 /* 0x18 */    _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x20 */    _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x28 */    _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
@@ -449,10 +500,10 @@
 /* 0x68 */    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
 /* 0x70 */    0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
 /* 0x78 */    0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
-/* 0x80 */    0x2b, 0x2c, 0x2d, 0x2e, _UNK, _UNK, 0x2f, 0x30,
-/* 0x88 */    0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, _UNK,
-/* 0x90 */    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, _UNK, _UNK,
-/* 0x98 */    _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x80 */    0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
+/* 0x88 */    0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
+/* 0x90 */    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
+/* 0x98 */    0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
 /* 0xA0 */    0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
 /* 0xA8 */    0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0xB0 */    _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
@@ -471,10 +522,11 @@
 static u8 aml_long_op_info_index[NUM_EXTENDED_OPCODE] =
 {
 /*              0     1     2     3     4     5     6     7  */
+/*              8     9     A     B     C     D     E     F  */
 /* 0x00 */    _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x08 */    _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x10 */    _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
-/* 0x18 */    _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x18 */    _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
 /* 0x20 */    0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
 /* 0x28 */    0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x30 */    0x55, 0x56, 0x57, _UNK, _UNK, _UNK, _UNK, _UNK,
@@ -488,11 +540,8 @@
 /* 0x70 */    _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x78 */    _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x80 */    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+/* 0x88 */    0x7C,
 };
-
-
-/*              0     1     2     3     4     5     6     7  */
-/* 0x00 */
 
 
 /*******************************************************************************
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/parser/psparse.c linux/drivers/acpi/parser/psparse.c
--- v2.4.0/linux/drivers/acpi/parser/psparse.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/parser/psparse.c	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: psparse - Parser top level AML parse routines
- *              $Revision: 71 $
+ *              $Revision: 74 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -537,6 +537,12 @@
 				 */
 
 				status = acpi_ds_get_predicate_value (walk_state, NULL, TRUE);
+				if (ACPI_FAILURE (status) &&
+					((status & AE_CODE_MASK) != AE_CODE_CONTROL))
+				{
+					return (status);
+				}
+
 				status = acpi_ps_next_parse_state (walk_state, op, status);
 			}
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/parser/psscope.c linux/drivers/acpi/parser/psscope.c
--- v2.4.0/linux/drivers/acpi/parser/psscope.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/parser/psscope.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: psscope - Parser scope stack management routines
- *              $Revision: 22 $
+ *              $Revision: 24 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/parser/pstree.c linux/drivers/acpi/parser/pstree.c
--- v2.4.0/linux/drivers/acpi/parser/pstree.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/parser/pstree.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: pstree - Parser op tree manipulation/traversal/search
- *              $Revision: 25 $
+ *              $Revision: 27 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/parser/psutils.c linux/drivers/acpi/parser/psutils.c
--- v2.4.0/linux/drivers/acpi/parser/psutils.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/parser/psutils.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: psutils - Parser miscellaneous utilities (Parser only)
- *              $Revision: 30 $
+ *              $Revision: 32 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/parser/pswalk.c linux/drivers/acpi/parser/pswalk.c
--- v2.4.0/linux/drivers/acpi/parser/pswalk.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/parser/pswalk.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: pswalk - Parser routines to walk parsed op tree(s)
- *              $Revision: 50 $
+ *              $Revision: 52 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/parser/psxface.c linux/drivers/acpi/parser/psxface.c
--- v2.4.0/linux/drivers/acpi/parser/psxface.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/parser/psxface.c	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: psxface - Parser external interfaces
- *              $Revision: 37 $
+ *              $Revision: 40 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -120,6 +120,12 @@
 	if (!op) {
 		return (AE_NO_MEMORY);
 	}
+
+
+	/* Init new op with the method name and pointer back to the NS node */
+
+	acpi_ps_set_name (op, method_node->name);
+	op->node = method_node;
 
 	/*
 	 * The walk of the parse tree is where we actually execute the method
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/power.c linux/drivers/acpi/power.c
--- v2.4.0/linux/drivers/acpi/power.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/power.c	Mon Jan 22 13:23:43 2001
@@ -81,12 +81,12 @@
 	buf.length = sizeof(obj);
 	buf.pointer = &obj;
 	if (!ACPI_SUCCESS(acpi_evaluate_object(ac_handle, "_PSR", NULL, &buf))
-		|| obj.type != ACPI_TYPE_NUMBER) {
+		|| obj.type != ACPI_TYPE_INTEGER) {
 		p += sprintf(p, "Could not read AC status\n");
 		goto end;
 	}
 
-	if (obj.number.value)
+	if (obj.integer.value)
 		p += sprintf(p, "on-line\n");
 	else
 		p += sprintf(p, "off-line\n");
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rsaddr.c linux/drivers/acpi/resources/rsaddr.c
--- v2.4.0/linux/drivers/acpi/resources/rsaddr.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rsaddr.c	Mon Jan 22 13:23:43 2001
@@ -4,12 +4,12 @@
  *                       Acpi_rs_address16_stream
  *                       Acpi_rs_address32_resource
  *                       Acpi_rs_address32_stream
- *              $Revision: 12 $
+ *              $Revision: 14 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rscalc.c linux/drivers/acpi/resources/rscalc.c
--- v2.4.0/linux/drivers/acpi/resources/rscalc.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rscalc.c	Mon Jan 22 13:23:43 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: rscalc - Acpi_rs_calculate_byte_stream_length
  *                       Acpi_rs_calculate_list_length
- *              $Revision: 16 $
+ *              $Revision: 18 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rscreate.c linux/drivers/acpi/resources/rscreate.c
--- v2.4.0/linux/drivers/acpi/resources/rscreate.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rscreate.c	Mon Jan 22 13:23:43 2001
@@ -3,12 +3,12 @@
  * Module Name: rscreate - Acpi_rs_create_resource_list
  *                         Acpi_rs_create_pci_routing_table
  *                         Acpi_rs_create_byte_stream
- *              $Revision: 22 $
+ *              $Revision: 24 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -223,9 +223,9 @@
 			/*
 			 * Dereference the Address
 			 */
-			if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) {
+			if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
 				user_prt->data.address =
-						(*sub_object_list)->number.value;
+						(*sub_object_list)->integer.value;
 			}
 
 			else {
@@ -237,9 +237,9 @@
 			 */
 			sub_object_list++;
 
-			if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) {
+			if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
 				user_prt->data.pin =
-						(u32) (*sub_object_list)->number.value;
+						(u32) (*sub_object_list)->integer.value;
 			}
 
 			else {
@@ -267,7 +267,7 @@
 				 * is NULL, since the entire buffer was zeroed
 				 * out, we can leave this alone.
 				 */
-				if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) {
+				if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
 					/*
 					 * Add to the Length field the length of
 					 * the u32 NULL
@@ -289,9 +289,9 @@
 			 */
 			sub_object_list++;
 
-			if (ACPI_TYPE_NUMBER == (*sub_object_list)->common.type) {
+			if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
 				user_prt->data.source_index =
-						(u32) (*sub_object_list)->number.value;
+						(u32) (*sub_object_list)->integer.value;
 			}
 
 			else {
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rsdump.c linux/drivers/acpi/resources/rsdump.c
--- v2.4.0/linux/drivers/acpi/resources/rsdump.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rsdump.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: rsdump - Functions do dump out the resource structures.
- *              $Revision: 13 $
+ *              $Revision: 15 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rsio.c linux/drivers/acpi/resources/rsio.c
--- v2.4.0/linux/drivers/acpi/resources/rsio.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rsio.c	Mon Jan 22 13:23:43 2001
@@ -6,12 +6,12 @@
  *                     Acpi_rs_fixed_io_stream
  *                     Acpi_rs_dma_resource
  *                     Acpi_rs_dma_stream
- *              $Revision: 10 $
+ *              $Revision: 12 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rsirq.c linux/drivers/acpi/resources/rsirq.c
--- v2.4.0/linux/drivers/acpi/resources/rsirq.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rsirq.c	Mon Jan 22 13:23:43 2001
@@ -4,12 +4,12 @@
  *                      Acpi_rs_irq_stream
  *                      Acpi_rs_extended_irq_resource
  *                      Acpi_rs_extended_irq_stream
- *              $Revision: 11 $
+ *              $Revision: 13 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rslist.c linux/drivers/acpi/resources/rslist.c
--- v2.4.0/linux/drivers/acpi/resources/rslist.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rslist.c	Mon Jan 22 13:23:43 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: rslist - Acpi_rs_byte_stream_to_list
  *                       Acpi_list_to_byte_stream
- *              $Revision: 8 $
+ *              $Revision: 10 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rsmemory.c linux/drivers/acpi/resources/rsmemory.c
--- v2.4.0/linux/drivers/acpi/resources/rsmemory.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rsmemory.c	Mon Jan 22 13:23:43 2001
@@ -6,12 +6,12 @@
  *                        Acpi_rs_fixed_memory32_resource
  *                        Acpi_rs_memory32_range_stream
  *                        Acpi_rs_fixed_memory32_stream
- *              $Revision: 10 $
+ *              $Revision: 12 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rsmisc.c linux/drivers/acpi/resources/rsmisc.c
--- v2.4.0/linux/drivers/acpi/resources/rsmisc.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rsmisc.c	Mon Jan 22 13:23:43 2001
@@ -8,12 +8,12 @@
  *                       Acpi_rs_end_dependent_functions_resource
  *                       Acpi_rs_start_dependent_functions_stream
  *                       Acpi_rs_end_dependent_functions_stream
- *              $Revision: 10 $
+ *              $Revision: 12 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rsutils.c linux/drivers/acpi/resources/rsutils.c
--- v2.4.0/linux/drivers/acpi/resources/rsutils.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rsutils.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: rsutils - Utilities for the resource manager
- *              $Revision: 12 $
+ *              $Revision: 14 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/resources/rsxface.c linux/drivers/acpi/resources/rsxface.c
--- v2.4.0/linux/drivers/acpi/resources/rsxface.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/resources/rsxface.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /*******************************************************************************
  *
  * Module Name: rsxface - Public interfaces to the ACPI subsystem
- *              $Revision: 8 $
+ *              $Revision: 10 $
  *
  ******************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/sys.c linux/drivers/acpi/sys.c
--- v2.4.0/linux/drivers/acpi/sys.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/sys.c	Mon Jan 29 10:15:59 2001
@@ -27,18 +27,13 @@
 #define _COMPONENT	OS_DEPENDENT
 	MODULE_NAME	("sys")
 
-#define ACPI_SLP_TYP(typa, typb)	(((int)(typa) << 8) | (int)(typb))
-#define ACPI_SLP_TYPA(value)		((value) >> 8)
-#define ACPI_SLP_TYPB(value)		((value) & 0xff)
-
 struct acpi_enter_sx_ctx
 {
 	wait_queue_head_t wait;
 	unsigned int      state;
 };
 
-volatile acpi_sstate_t acpi_sleep_state = ACPI_S0;
-static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,};
+volatile acpi_sstate_t acpi_sleep_state = ACPI_STATE_S0;
 
 /*
  * Enter system sleep state
@@ -50,56 +45,32 @@
 	ACPI_OBJECT_LIST arg_list;
 	ACPI_OBJECT arg;
 
-	/*
-         * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
-	 */
-
-	// run the _PTS method
-	memset(&arg_list, 0, sizeof(arg_list));
-	arg_list.count = 1;
-	arg_list.pointer = &arg;
+	acpi_enter_sleep_state(ctx->state);
 
-	memset(&arg, 0, sizeof(arg));
-	arg.type = ACPI_TYPE_NUMBER;
-	arg.number.value = ctx->state;
-
-	acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
-	
-	// clear wake status by writing a 1
-	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);
-		
-	acpi_sleep_state = ctx->state;
-
-	// set ACPI_SLP_TYPA/b and ACPI_SLP_EN
-	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_TYPE_A,
-		ACPI_SLP_TYPA(acpi_slptyp[ctx->state]));
-	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_TYPE_B,
-		ACPI_SLP_TYPB(acpi_slptyp[ctx->state]));
-	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_EN, 1);
-	
-	if (ctx->state != ACPI_S1) {
-		/* we should have just shut off - what are we doing here? */
-		printk(KERN_ERR "ACPI: S%d failed\n", ctx->state);
+	/* either we are in S1, or the transition failed, as the other states resume
+           from the waking vector */
+	if (ctx->state != ACPI_STATE_S1) {
+		printk(KERN_ERR "Could not enter S%d\n", ctx->state);
 		goto out;
 	}
 
-	// wait until S1 is entered
+	/* wait until S1 is entered */
 	while (!(acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, WAK_STS)))
 		safe_halt();
 
-	// run the _WAK method
+	/* run the _WAK method */
 	memset(&arg_list, 0, sizeof(arg_list));
 	arg_list.count = 1;
 	arg_list.pointer = &arg;
 
 	memset(&arg, 0, sizeof(arg));
-	arg.type = ACPI_TYPE_NUMBER;
-	arg.number.value = ctx->state;
+	arg.type = ACPI_TYPE_INTEGER;
+	arg.integer.value = ctx->state;
 
 	acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL);
 
  out:
-	acpi_sleep_state = ACPI_S0;
+	acpi_sleep_state = ACPI_STATE_S0;
 
 	if (waitqueue_active(&ctx->wait))
 		wake_up_interruptible(&ctx->wait);
@@ -112,13 +83,9 @@
 acpi_power_off(void)
 {
 	struct acpi_enter_sx_ctx ctx;
-
-	if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
-	    || acpi_slptyp[ACPI_S5] == ACPI_INVALID)
-		return;
 	
 	init_waitqueue_head(&ctx.wait);
-	ctx.state = ACPI_S5;
+	ctx.state = ACPI_STATE_S5;
 	acpi_enter_sx_async(&ctx);
 }
 
@@ -132,10 +99,6 @@
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
 
-	if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
-	    || acpi_slptyp[state] == ACPI_INVALID)
-		return -EINVAL;
-	
 	init_waitqueue_head(&ctx.wait);
 	ctx.state = state;
 
@@ -166,18 +129,13 @@
 
 	printk(KERN_INFO "ACPI: System firmware supports:");
 
-	for (sx = ACPI_S0; sx <= ACPI_S5; sx++) {
-		int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1);
+	for (sx = ACPI_STATE_S0; sx <= ACPI_STATE_S5; sx++) {
 		if (ACPI_SUCCESS(
-			   acpi_hw_obtain_sleep_type_register_data(ca_sx,
+			   acpi_hw_obtain_sleep_type_register_data(sx,
 								   &type_a,
 								   &type_b))) {
 
-			acpi_slptyp[sx] = ACPI_SLP_TYP(type_a, type_b);
 			printk(" S%d", sx);
-		}
-		else {
-			acpi_slptyp[sx] = ACPI_INVALID;
 		}
 	}
 	printk("\n");
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/table.c linux/drivers/acpi/table.c
--- v2.4.0/linux/drivers/acpi/table.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/table.c	Mon Jan 29 10:15:59 2001
@@ -47,21 +47,6 @@
 		return -ENODEV;
 	}
 
-	if (acpi_fadt.plvl2_lat
-	    && acpi_fadt.plvl2_lat <= ACPI_MAX_P_LVL2_LAT) {
-		acpi_c2_exit_latency
-			= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat);
-		acpi_c2_enter_latency
-			= ACPI_MICROSEC_TO_TMR_TICKS(ACPI_TMR_HZ / 1000);
-	}
-	if (acpi_fadt.plvl3_lat
-	    && acpi_fadt.plvl3_lat <= ACPI_MAX_P_LVL3_LAT) {
-		acpi_c3_exit_latency
-			= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat);
-		acpi_c3_enter_latency
-			= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 5);
-	}
-
 	return 0;
 }
 
@@ -71,11 +56,7 @@
 int
 acpi_find_and_load_tables(u64 rsdp)
 {
-	if (ACPI_SUCCESS(acpi_load_tables(rsdp)))
-	{
-		printk(KERN_INFO "ACPI: System description tables loaded\n");
-	}
-	else {
+	if (!ACPI_SUCCESS(acpi_load_tables(rsdp))) {
 		printk(KERN_INFO "ACPI: System description table load failed\n");
 		acpi_terminate();
 		return -1;
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/tables/tbconvrt.c linux/drivers/acpi/tables/tbconvrt.c
--- v2.4.0/linux/drivers/acpi/tables/tbconvrt.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/tables/tbconvrt.c	Mon Jan 29 10:15:59 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: tbconvrt - ACPI Table conversion utilities
- *              $Revision: 15 $
+ *              $Revision: 18 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -47,7 +47,7 @@
 			   a.register_bit_width = (u8) MUL_8 (b);\
 			   a.register_bit_offset = 0;\
 			   a.reserved = 0;\
-			   a.address = (UINT64) c;}
+			   ACPI_STORE_ADDRESS (a.address,c);}
 
 
 /* ACPI V1.0 entries -- address space is always I/O */
@@ -126,8 +126,8 @@
 			new_table->table_offset_entry[i] =
 				((RSDT_DESCRIPTOR_REV071 *) table_info->pointer)->table_offset_entry[i];
 #else
-			new_table->table_offset_entry[i] =
-				((RSDT_DESCRIPTOR_REV1 *) table_info->pointer)->table_offset_entry[i];
+			ACPI_STORE_ADDRESS (new_table->table_offset_entry[i],
+				((RSDT_DESCRIPTOR_REV1 *) table_info->pointer)->table_offset_entry[i]);
 #endif
 		}
 		else {
@@ -312,11 +312,11 @@
 		/* No 0.71 equivalence. Leave pre-zeroed. */
 		/* FADT2->Flush_stride = 0; */
 
-		/* Processor’s duty cycle index in processor's P_CNT reg*/
+		/* Processor's duty cycle index in processor's P_CNT reg*/
 		/* No 0.71 equivalence. Leave pre-zeroed. */
 		/* FADT2->Duty_offset = 0; */
 
-		/* Processor’s duty cycle value bit width in P_CNT register.*/
+		/* Processor's duty cycle value bit width in P_CNT register.*/
 		/* No 0.71 equivalence. Leave pre-zeroed. */
 		/* FADT2->Duty_width = 0; */
 
@@ -384,8 +384,8 @@
 
 		/* Convert table pointers to 64-bit fields */
 
-		FADT2->Xfirmware_ctrl = (UINT64) FADT1->firmware_ctrl;
-		FADT2->Xdsdt         = (UINT64) FADT1->dsdt;
+		ACPI_STORE_ADDRESS (FADT2->Xfirmware_ctrl, FADT1->firmware_ctrl);
+		ACPI_STORE_ADDRESS (FADT2->Xdsdt, FADT1->dsdt);
 
 		/* System Interrupt Model isn't used in ACPI 2.0*/
 		/* FADT2->Reserved1 = 0; */
@@ -448,6 +448,7 @@
 	 * Global FADT pointer will point to the common V2.0 FADT
 	 */
 	acpi_gbl_FADT = FADT2;
+	acpi_gbl_FADT->header.length = sizeof (FADT_DESCRIPTOR);
 
 
 	/* Free the original table */
@@ -463,8 +464,6 @@
 	table_desc->allocation = ACPI_MEM_ALLOCATED;
 	table_desc->length = sizeof (FADT_DESCRIPTOR_REV2);
 
-
-	/* Dump the FADT Header */
 
 	/* Dump the entire FADT */
 
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/tables/tbget.c linux/drivers/acpi/tables/tbget.c
--- v2.4.0/linux/drivers/acpi/tables/tbget.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/tables/tbget.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: tbget - ACPI Table get* routines
- *              $Revision: 40 $
+ *              $Revision: 43 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -243,7 +243,7 @@
 		/* Get the table via the XSDT */
 
 		status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS)
-				 acpi_gbl_XSDT->table_offset_entry[index],
+				 ACPI_GET_ADDRESS (acpi_gbl_XSDT->table_offset_entry[index]),
 				 table_ptr, &table_info);
 
 		/* Ignore a table that failed verification */
@@ -326,7 +326,8 @@
 	 * Get the DSDT (We know that the FADT is valid now)
 	 */
 
-	status = acpi_tb_get_table (acpi_gbl_FADT->Xdsdt, table_ptr, &table_info);
+	status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xdsdt),
+			  table_ptr, &table_info);
 	if (ACPI_FAILURE (status)) {
 		return (status);
 	}
@@ -472,13 +473,14 @@
 		/* 0.71 RSDP has 64bit Rsdt address field */
 		physical_address = ((RSDP_DESCRIPTOR_REV071 *)acpi_gbl_RSDP)->rsdt_physical_address;
 #else
-		physical_address = acpi_gbl_RSDP->rsdt_physical_address;
+		physical_address = (ACPI_PHYSICAL_ADDRESS) acpi_gbl_RSDP->rsdt_physical_address;
 #endif
 		table_signature = RSDT_SIG;
 		signature_length = sizeof (RSDT_SIG) -1;
 	}
 	else {
-		physical_address = (ACPI_PHYSICAL_ADDRESS) acpi_gbl_RSDP->xsdt_physical_address;
+		physical_address = (ACPI_PHYSICAL_ADDRESS)
+				   ACPI_GET_ADDRESS (acpi_gbl_RSDP->xsdt_physical_address);
 		table_signature = XSDT_SIG;
 		signature_length = sizeof (XSDT_SIG) -1;
 	}
@@ -586,7 +588,7 @@
 	else {
 		/* Just map the physical memory to our address space */
 
-		status = acpi_tb_map_acpi_table (acpi_gbl_FADT->Xfirmware_ctrl,
+		status = acpi_tb_map_acpi_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xfirmware_ctrl),
 				   &size, &table_ptr);
 		if (ACPI_FAILURE(status)) {
 			return (status);
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/tables/tbinstal.c linux/drivers/acpi/tables/tbinstal.c
--- v2.4.0/linux/drivers/acpi/tables/tbinstal.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/tables/tbinstal.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: tbinstal - ACPI table installation and removal
- *              $Revision: 34 $
+ *              $Revision: 36 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/tables/tbutils.c linux/drivers/acpi/tables/tbutils.c
--- v2.4.0/linux/drivers/acpi/tables/tbutils.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/tables/tbutils.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: tbutils - Table manipulation utilities
- *              $Revision: 31 $
+ *              $Revision: 33 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/tables/tbxface.c linux/drivers/acpi/tables/tbxface.c
--- v2.4.0/linux/drivers/acpi/tables/tbxface.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/tables/tbxface.c	Mon Jan 22 13:23:43 2001
@@ -2,12 +2,12 @@
  *
  * Module Name: tbxface - Public interfaces to the ACPI subsystem
  *                         ACPI table oriented interfaces
- *              $Revision: 32 $
+ *              $Revision: 34 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/tables/tbxfroot.c linux/drivers/acpi/tables/tbxfroot.c
--- v2.4.0/linux/drivers/acpi/tables/tbxfroot.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/tables/tbxfroot.c	Mon Jan 22 13:23:43 2001
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
  * Module Name: tbxfroot - Find the root ACPI table (RSDT)
- *              $Revision: 33 $
+ *              $Revision: 35 $
  *
  *****************************************************************************/
 
 /*
- *  Copyright (C) 2000 R. Byron Moore
+ *  Copyright (C) 2000, 2001 R. Byron Moore
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.4.0/linux/drivers/atm/Makefile linux/drivers/atm/Makefile
--- v2.4.0/linux/drivers/atm/Makefile	Fri Dec 29 14:07:21 2000
+++ linux/drivers/atm/Makefile	Sat Jan 20 16:27:44 2001
@@ -46,7 +46,7 @@
   endif
 endif
 
-obj-$(CONFIG_ATM_FORE200E) += fore200e.o $(FORE200E_FW_OBJS)
+obj-$(CONFIG_ATM_FORE200E) += fore_200e.o
 
 EXTRA_CFLAGS=-g
 
diff -u --recursive --new-file v2.4.0/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.4.0/linux/drivers/block/DAC960.c	Thu Dec  7 17:08:24 2000
+++ linux/drivers/block/DAC960.c	Sat Jan 20 08:51:40 2001
@@ -1820,7 +1820,6 @@
       Request->nr_segments < Controller->DriverScatterGatherLimit)
     {
       Request->nr_segments++;
-      RequestQueue->elevator.nr_segments++;
       return true;
     }
   return false;
@@ -1844,7 +1843,6 @@
       Request->nr_segments < Controller->DriverScatterGatherLimit)
     {
       Request->nr_segments++;
-      RequestQueue->elevator.nr_segments++;
       return true;
     }
   return false;
@@ -1864,17 +1862,12 @@
   DAC960_Controller_T *Controller =
     (DAC960_Controller_T *) RequestQueue->queuedata;
   int TotalSegments = Request->nr_segments + NextRequest->nr_segments;
-  int SameSegment = 0;
   if (Request->bhtail->b_data + Request->bhtail->b_size
       == NextRequest->bh->b_data)
-    {
       TotalSegments--;
-      SameSegment = 1;
-    }
   if (TotalSegments > MaxSegments ||
       TotalSegments > Controller->DriverScatterGatherLimit)
     return false;
-  RequestQueue->elevator.nr_segments -= SameSegment;
   Request->nr_segments = TotalSegments;
   return true;
 }
@@ -2834,6 +2827,7 @@
 static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
 						 boolean SuccessfulIO)
 {
+  blk_finished_io(BufferHeader->b_size >> 9);
   BufferHeader->b_end_io(BufferHeader, SuccessfulIO);
 }
 
diff -u --recursive --new-file v2.4.0/linux/drivers/block/cciss.c linux/drivers/block/cciss.c
--- v2.4.0/linux/drivers/block/cciss.c	Thu Jan  4 12:50:12 2001
+++ linux/drivers/block/cciss.c	Sat Jan 20 08:46:29 2001
@@ -1086,6 +1086,7 @@
 	{
 		xbh = bh->b_reqnext; 
 		bh->b_reqnext = NULL; 
+		blk_finished_io(bh->b_size >> 9);
 		bh->b_end_io(bh, status);
 		bh = xbh;
 	}
diff -u --recursive --new-file v2.4.0/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- v2.4.0/linux/drivers/block/cpqarray.c	Thu Nov 16 11:30:29 2000
+++ linux/drivers/block/cpqarray.c	Sat Jan 20 08:51:40 2001
@@ -140,23 +140,7 @@
 static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
 static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io);
 
-static void do_ida_request(int i);
-/*
- * This is a hack.  This driver eats a major number for each controller, and
- * sets blkdev[xxx].request_fn to each one of these so the real request
- * function knows what controller its working with.
- */
-#define DO_IDA_REQUEST(x) { do_ida_request(x); }
-
-static void do_ida_request0(request_queue_t * q) DO_IDA_REQUEST(0);
-static void do_ida_request1(request_queue_t * q) DO_IDA_REQUEST(1);
-static void do_ida_request2(request_queue_t * q) DO_IDA_REQUEST(2);
-static void do_ida_request3(request_queue_t * q) DO_IDA_REQUEST(3);
-static void do_ida_request4(request_queue_t * q) DO_IDA_REQUEST(4);
-static void do_ida_request5(request_queue_t * q) DO_IDA_REQUEST(5);
-static void do_ida_request6(request_queue_t * q) DO_IDA_REQUEST(6);
-static void do_ida_request7(request_queue_t * q) DO_IDA_REQUEST(7);
-
+static void do_ida_request(request_queue_t *q);
 static void start_io(ctlr_info_t *h);
 
 static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c);
@@ -362,6 +346,47 @@
 }
 #endif /* MODULE */
 
+static inline int cpq_new_segment(request_queue_t *q, struct request *rq,
+				  int max_segments)
+{
+	if (rq->nr_segments < SG_MAX) {
+		rq->nr_segments++;
+		return 1;
+	}
+	return 0;
+}
+
+static int cpq_back_merge_fn(request_queue_t *q, struct request *rq,
+			     struct buffer_head *bh, int max_segments)
+{
+	if (rq->bhtail->b_data + rq->bhtail->b_size == bh->b_data)
+		return 1;
+	return cpq_new_segment(q, rq, max_segments);
+}
+
+static int cpq_front_merge_fn(request_queue_t *q, struct request *rq,
+			     struct buffer_head *bh, int max_segments)
+{
+	if (bh->b_data + bh->b_size == rq->bh->b_data)
+		return 1;
+	return cpq_new_segment(q, rq, max_segments);
+}
+
+static int cpq_merge_requests_fn(request_queue_t *q, struct request *rq,
+				 struct request *nxt, int max_segments)
+{
+	int total_segments = rq->nr_segments + nxt->nr_segments;
+
+	if (rq->bhtail->b_data + rq->bhtail->b_size == nxt->bh->b_data)
+		total_segments--;
+
+	if (total_segments > SG_MAX)
+		return 0;
+
+	rq->nr_segments = total_segments;
+	return 1;
+}
+
 /*
  *  This is it.  Find all the controllers and register them.  I really hate
  *  stealing all these major device numbers.
@@ -369,12 +394,7 @@
  */
 int __init cpqarray_init(void)
 {
-	void (*request_fns[MAX_CTLR])(request_queue_t *) = {
-		do_ida_request0, do_ida_request1,
-		do_ida_request2, do_ida_request3,
-		do_ida_request4, do_ida_request5,
-		do_ida_request6, do_ida_request7,
-	};
+	request_queue_t *q;
 	int i,j;
 	int num_cntlrs_reg = 0;
 
@@ -495,16 +515,20 @@
 
 		hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
 
-
 		ida_procinit(i);
 
-		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 
-			request_fns[i]);		
-		blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 0);
+		q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+		q->queuedata = hba[i];
+		blk_init_queue(q, do_ida_request);
+		blk_queue_headactive(q, 0);
 		blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256);
 		hardsect_size[MAJOR_NR+i] = ida_hardsizes + (i*256);
 		read_ahead[MAJOR_NR+i] = READ_AHEAD;
 
+		q->back_merge_fn = cpq_back_merge_fn;
+		q->front_merge_fn = cpq_front_merge_fn;
+		q->merge_requests_fn = cpq_merge_requests_fn;
+
 		ida_gendisk[i].major = MAJOR_NR + i;
 		ida_gendisk[i].major_name = "ida";
 		ida_gendisk[i].minor_shift = NWD_SHIFT;
@@ -872,37 +896,30 @@
  * are in here (either via the dummy do_ida_request functions or by being
  * called from the interrupt handler
  */
-static void do_ida_request(int ctlr)
+static void do_ida_request(request_queue_t *q)
 {
-	ctlr_info_t *h = hba[ctlr];
+	ctlr_info_t *h = q->queuedata;
 	cmdlist_t *c;
 	int seg, sect;
 	char *lastdataend;
-	struct list_head * queue_head;
+	struct list_head * queue_head = &q->queue_head;
 	struct buffer_head *bh;
 	struct request *creq;
 
-	queue_head = &blk_dev[MAJOR_NR+ctlr].request_queue.queue_head;
-
-	if (list_empty(queue_head))
-	{
+	if (q->plugged || list_empty(queue_head)) {
 		start_io(h);
 		return;
 	}
 
 	creq = blkdev_entry_next_request(queue_head);
-	if (creq->rq_status == RQ_INACTIVE)
-	{	
-                start_io(h);
-                return;
-        }
-
+	if (creq->nr_segments > SG_MAX)
+		BUG();
 
-	if (ctlr != MAJOR(creq->rq_dev)-MAJOR_NR ||
-		ctlr > nr_ctlr || h == NULL) 
+	if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR || h->ctlr > nr_ctlr)
 	{
 		printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
-				ctlr, creq->rq_dev, creq);
+				h->ctlr, creq->rq_dev, creq);
+		blkdev_dequeue_request(creq);
 		complete_buffers(creq->bh, 0);
 		start_io(h);
                 return;
@@ -916,12 +933,12 @@
 
 	bh = creq->bh;
 
-	c->ctlr = ctlr;
+	c->ctlr = h->ctlr;
 	c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
 	c->hdr.size = sizeof(rblk_t) >> 2;
 	c->size += sizeof(rblk_t);
 
-	c->req.hdr.blk = ida[(ctlr<<CTLR_SHIFT) + MINOR(creq->rq_dev)].start_sect + creq->sector;
+	c->req.hdr.blk = ida[(h->ctlr<<CTLR_SHIFT) + MINOR(creq->rq_dev)].start_sect + creq->sector;
 	c->bh = bh;
 DBGPX(
 	if (bh == NULL)
@@ -933,21 +950,16 @@
 	sect = 0;
 	while(bh) {
 		sect += bh->b_size/512;
-DBGPX(
-		if (bh->b_size % 512) {
-			printk("Oh damn.  %d+%d, size = %d\n", creq->sector, sect, bh->b_size);
-			panic("b_size %% 512 != 0");
-		}
-);
 		if (bh->b_data == lastdataend) {
 			c->req.sg[seg-1].size += bh->b_size;
 			lastdataend += bh->b_size;
 		} else {
+			if (seg == SG_MAX)
+				BUG();
 			c->req.sg[seg].size = bh->b_size;
 			c->req.sg[seg].addr = (__u32)virt_to_bus(bh->b_data);
 			lastdataend = bh->b_data + bh->b_size;
-			if (++seg == SG_MAX)
-				break;
+			seg++;
 		}
 		bh = bh->b_reqnext;
 	}
@@ -955,30 +967,24 @@
 	c->req.hdr.sg_cnt = seg;
 	c->req.hdr.blk_cnt = sect;
 
-	creq->sector += sect;
-	creq->nr_sectors -= sect;
-
-	/* Ready the next request:
-	 * Fix up creq if we still have more buffers in the buffer chain, or
-	 * mark this request as done and ready the next one.
+	/*
+	 * Since we control our own merging, we know that this request
+	 * is now fully setup and there's nothing left.
          */
-	if (creq->nr_sectors) {
-DBGPX(
-		if (bh==NULL) {
-			printk("sector=%d, nr_sectors=%d, sect=%d, seg=%d\n",
-				creq->sector, creq->nr_sectors, sect, seg);
-			panic("mother...");
-		}
-);
-		creq->bh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
-DBGPX(		printk("More to do on same request %p\n", creq); );
-	} else {
-DBGPX(		printk("Done with %p\n", creq); );
-		blkdev_dequeue_request(creq);
-		end_that_request_last(creq);
+	if (creq->nr_sectors != sect) {
+		printk("ida: %ld != %d sectors\n", creq->nr_sectors, sect);
+		BUG();
 	}
 
+	blkdev_dequeue_request(creq);
+
+	/*
+	 * ehh, we can't really end the request here since it's not
+	 * even started yet. for now it shouldn't hurt though
+	 */
+DBGPX(	printk("Done with %p\n", creq); );
+	end_that_request_last(creq);
+
 	c->req.hdr.cmd = (creq->cmd == READ) ? IDA_READ : IDA_WRITE;
 	c->type = CMD_RWREQ;
 
@@ -1025,6 +1031,7 @@
 		xbh = bh->b_reqnext;
 		bh->b_reqnext = NULL;
 		
+		blk_finished_io(bh->b_size >> 9);
 		bh->b_end_io(bh, ok);
 
 		bh = xbh;
@@ -1072,7 +1079,6 @@
 	unsigned long flags;
 	__u32 a,a1;
 
-
 	istat = h->access.intr_pending(h);
 	/* Is this interrupt for us? */
 	if (istat == 0)
@@ -1116,7 +1122,7 @@
 	/*
 	 * See if we can queue up some more IO
 	 */
-	do_ida_request(h->ctlr);
+	do_ida_request(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr));
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
diff -u --recursive --new-file v2.4.0/linux/drivers/block/elevator.c linux/drivers/block/elevator.c
--- v2.4.0/linux/drivers/block/elevator.c	Tue Dec  5 15:05:26 2000
+++ linux/drivers/block/elevator.c	Mon Jan 15 13:08:15 2001
@@ -24,125 +24,115 @@
 #include <linux/blkdev.h>
 #include <linux/elevator.h>
 #include <linux/blk.h>
+#include <linux/module.h>
 #include <asm/uaccess.h>
 
-/*
- * Order ascending, but only allow a request to be skipped a certain
- * number of times
- */
-void elevator_linus(struct request *req, elevator_t *elevator,
-		    struct list_head *real_head,
-		    struct list_head *head, int orig_latency)
-{
-	struct list_head *entry = real_head;
-	struct request *tmp;
-
-	req->elevator_sequence = orig_latency;
-
-	while ((entry = entry->prev) != head) {
-		tmp = blkdev_entry_to_request(entry);
-		if (IN_ORDER(tmp, req))
-			break;
-		if (!tmp->elevator_sequence)
-			break;
-		tmp->elevator_sequence--;
-	}
-	list_add(&req->queue, entry);
-}
-
 int elevator_linus_merge(request_queue_t *q, struct request **req,
+			 struct list_head * head,
 			 struct buffer_head *bh, int rw,
-			 int *max_sectors, int *max_segments)
+			 int max_sectors, int max_segments)
 {
-	struct list_head *entry, *head = &q->queue_head;
+	struct list_head *entry = &q->queue_head;
 	unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE;
 
-	entry = head;
-	if (q->head_active && !q->plugged)
-		head = head->next;
-
 	while ((entry = entry->prev) != head) {
-		struct request *__rq = *req = blkdev_entry_to_request(entry);
+		struct request *__rq = blkdev_entry_to_request(entry);
+
+		/*
+		 * simply "aging" of requests in queue
+		 */
+		if (__rq->elevator_sequence-- <= 0) {
+			*req = __rq;
+			break;
+		}
+
 		if (__rq->sem)
 			continue;
 		if (__rq->cmd != rw)
 			continue;
-		if (__rq->nr_sectors + count > *max_sectors)
-			continue;
 		if (__rq->rq_dev != bh->b_rdev)
 			continue;
+		if (__rq->nr_sectors + count > max_sectors)
+			continue;
+		if (__rq->elevator_sequence < count)
+			break;
 		if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
 			ret = ELEVATOR_BACK_MERGE;
+			*req = __rq;
 			break;
-		}
-		if (!__rq->elevator_sequence)
-			break;
-		if (__rq->sector - count == bh->b_rsector) {
-			__rq->elevator_sequence--;
+		} else if (__rq->sector - count == bh->b_rsector) {
 			ret = ELEVATOR_FRONT_MERGE;
+			__rq->elevator_sequence -= count;
+			*req = __rq;
 			break;
-		}
+		} else if (!*req && BHRQ_IN_ORDER(bh, __rq))
+			*req = __rq;
 	}
 
+	return ret;
+}
+
+void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int count)
+{
+	struct list_head *entry = &req->queue, *head = &q->queue_head;
+
 	/*
 	 * second pass scan of requests that got passed over, if any
 	 */
-	if (ret != ELEVATOR_NO_MERGE && *req) {
-		while ((entry = entry->next) != &q->queue_head) {
-			struct request *tmp = blkdev_entry_to_request(entry);
-			tmp->elevator_sequence--;
-		}
+	while ((entry = entry->next) != head) {
+		struct request *tmp = blkdev_entry_to_request(entry);
+		tmp->elevator_sequence -= count;
 	}
-
-	return ret;
 }
 
-/*
- * No request sorting, just add it to the back of the list
- */
-void elevator_noop(struct request *req, elevator_t *elevator,
-		   struct list_head *real_head, struct list_head *head,
-		   int orig_latency)
+void elevator_linus_merge_req(struct request *req, struct request *next)
 {
-	list_add_tail(&req->queue, real_head);
+	if (next->elevator_sequence < req->elevator_sequence)
+		req->elevator_sequence = next->elevator_sequence;
 }
 
 /*
- * See if we can find a request that is buffer can be coalesced with.
+ * See if we can find a request that this buffer can be coalesced with.
  */
 int elevator_noop_merge(request_queue_t *q, struct request **req,
+			struct list_head * head,
 			struct buffer_head *bh, int rw,
-			int *max_sectors, int *max_segments)
+			int max_sectors, int max_segments)
 {
-	struct list_head *entry, *head = &q->queue_head;
+	struct list_head *entry;
 	unsigned int count = bh->b_size >> 9;
 
-	if (q->head_active && !q->plugged)
-		head = head->next;
+	if (list_empty(&q->queue_head))
+		return ELEVATOR_NO_MERGE;
 
-	entry = head;
+	entry = &q->queue_head;
 	while ((entry = entry->prev) != head) {
-		struct request *__rq = *req = blkdev_entry_to_request(entry);
-		if (__rq->sem)
-			continue;
+		struct request *__rq = blkdev_entry_to_request(entry);
+
 		if (__rq->cmd != rw)
 			continue;
-		if (__rq->nr_sectors + count > *max_sectors)
-			continue;
 		if (__rq->rq_dev != bh->b_rdev)
 			continue;
-		if (__rq->sector + __rq->nr_sectors == bh->b_rsector)
+		if (__rq->nr_sectors + count > max_sectors)
+			continue;
+		if (__rq->sem)
+			continue;
+		if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
+			*req = __rq;
 			return ELEVATOR_BACK_MERGE;
-		if (__rq->sector - count == bh->b_rsector)
+		} else if (__rq->sector - count == bh->b_rsector) {
+			*req = __rq;
 			return ELEVATOR_FRONT_MERGE;
+		}
 	}
+
+	*req = blkdev_entry_to_request(q->queue_head.prev);
 	return ELEVATOR_NO_MERGE;
 }
 
-/*
- * The noop "elevator" does not do any accounting
- */
-void elevator_noop_dequeue(struct request *req) {}
+void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int count) {}
+
+void elevator_noop_merge_req(struct request *req, struct request *next) {}
 
 int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg)
 {
diff -u --recursive --new-file v2.4.0/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.4.0/linux/drivers/block/ll_rw_blk.c	Sun Dec 31 11:16:58 2000
+++ linux/drivers/block/ll_rw_blk.c	Mon Jan 29 12:11:32 2001
@@ -19,6 +19,7 @@
 #include <linux/config.h>
 #include <linux/locks.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 
@@ -38,8 +39,6 @@
 extern int mac_floppy_init(void);
 #endif
 
-extern int lvm_init(void);
-
 /*
  * For the allocated request tables
  */
@@ -118,6 +117,19 @@
  */
 int * max_sectors[MAX_BLKDEV];
 
+/*
+ * queued sectors for all devices, used to make sure we don't fill all
+ * of memory with locked buffers
+ */
+atomic_t queued_sectors;
+
+/*
+ * high and low watermark for above
+ */
+static int high_queued_sectors, low_queued_sectors;
+static int batch_requests, queue_nr_requests;
+static DECLARE_WAIT_QUEUE_HEAD(blk_buffers_wait);
+
 static inline int get_max_sectors(kdev_t dev)
 {
 	if (!max_sectors[MAJOR(dev)])
@@ -125,7 +137,7 @@
 	return max_sectors[MAJOR(dev)][MINOR(dev)];
 }
 
-static inline request_queue_t *__blk_get_queue(kdev_t dev)
+inline request_queue_t *__blk_get_queue(kdev_t dev)
 {
 	struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
 
@@ -153,17 +165,14 @@
 
 static int __blk_cleanup_queue(struct list_head *head)
 {
-	struct list_head *entry;
 	struct request *rq;
 	int i = 0;
 
 	if (list_empty(head))
 		return 0;
 
-	entry = head->next;
 	do {
-		rq = list_entry(entry, struct request, table);
-		entry = entry->next;
+		rq = list_entry(head->next, struct request, table);
 		list_del(&rq->table);
 		kmem_cache_free(request_cachep, rq);
 		i++;
@@ -188,10 +197,12 @@
  **/
 void blk_cleanup_queue(request_queue_t * q)
 {
-	int count = QUEUE_NR_REQUESTS;
+	int count = queue_nr_requests;
 
 	count -= __blk_cleanup_queue(&q->request_freelist[READ]);
 	count -= __blk_cleanup_queue(&q->request_freelist[WRITE]);
+	count -= __blk_cleanup_queue(&q->pending_freelist[READ]);
+	count -= __blk_cleanup_queue(&q->pending_freelist[WRITE]);
 
 	if (count)
 		printk("blk_cleanup_queue: leaked requests (%d)\n", count);
@@ -290,7 +301,6 @@
 {
 	if (req->nr_segments < max_segments) {
 		req->nr_segments++;
-		q->elevator.nr_segments++;
 		return 1;
 	}
 	return 0;
@@ -316,18 +326,13 @@
 				struct request *next, int max_segments)
 {
 	int total_segments = req->nr_segments + next->nr_segments;
-	int same_segment;
 
-	same_segment = 0;
-	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) {
+	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data)
 		total_segments--;
-		same_segment = 1;
-	}
     
 	if (total_segments > max_segments)
 		return 0;
 
-	q->elevator.nr_segments -= same_segment;
 	req->nr_segments = total_segments;
 	return 1;
 }
@@ -364,7 +369,7 @@
 	}
 }
 
-static void generic_unplug_device(void *data)
+void generic_unplug_device(void *data)
 {
 	request_queue_t *q = (request_queue_t *) data;
 	unsigned long flags;
@@ -379,19 +384,24 @@
 	struct request *rq;
 	int i;
 
+	INIT_LIST_HEAD(&q->request_freelist[READ]);
+	INIT_LIST_HEAD(&q->request_freelist[WRITE]);
+	INIT_LIST_HEAD(&q->pending_freelist[READ]);
+	INIT_LIST_HEAD(&q->pending_freelist[WRITE]);
+	q->pending_free[READ] = q->pending_free[WRITE] = 0;
+
 	/*
-	 * Divide requests in half between read and write. This used to
-	 * be a 2/3 advantage for reads, but now reads can steal from
-	 * the write free list.
+	 * Divide requests in half between read and write
 	 */
-	for (i = 0; i < QUEUE_NR_REQUESTS; i++) {
+	for (i = 0; i < queue_nr_requests; i++) {
 		rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL);
+		memset(rq, 0, sizeof(struct request));
 		rq->rq_status = RQ_INACTIVE;
 		list_add(&rq->table, &q->request_freelist[i & 1]);
 	}
 
 	init_waitqueue_head(&q->wait_for_request);
-	spin_lock_init(&q->request_lock);
+	spin_lock_init(&q->queue_lock);
 }
 
 static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh);
@@ -426,14 +436,12 @@
  *    blk_queue_headactive().
  *
  * Note:
- *    blk_init_queue() must be paired with a blk_cleanup-queue() call
+ *    blk_init_queue() must be paired with a blk_cleanup_queue() call
  *    when the block device is deactivated (such as at module unload).
  **/
 void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
 {
 	INIT_LIST_HEAD(&q->queue_head);
-	INIT_LIST_HEAD(&q->request_freelist[READ]);
-	INIT_LIST_HEAD(&q->request_freelist[WRITE]);
 	elevator_init(&q->elevator, ELEVATOR_LINUS);
 	blk_init_free_list(q);
 	q->request_fn     	= rfn;
@@ -455,7 +463,6 @@
 	q->head_active    	= 1;
 }
 
-
 #define blkdev_free_rq(list) list_entry((list)->next, struct request, table);
 /*
  * Get a free request. io_request_lock must be held and interrupts
@@ -463,37 +470,16 @@
  */
 static inline struct request *get_request(request_queue_t *q, int rw)
 {
-	struct list_head *list = &q->request_freelist[rw];
-	struct request *rq;
-
-	/*
-	 * Reads get preferential treatment and are allowed to steal
-	 * from the write free list if necessary.
-	 */
-	if (!list_empty(list)) {
-		rq = blkdev_free_rq(list);
-		goto got_rq;
-	}
+	struct request *rq = NULL;
 
-	/*
-	 * if the WRITE list is non-empty, we know that rw is READ
-	 * and that the READ list is empty. allow reads to 'steal'
-	 * from the WRITE list.
-	 */
-	if (!list_empty(&q->request_freelist[WRITE])) {
-		list = &q->request_freelist[WRITE];
-		rq = blkdev_free_rq(list);
-		goto got_rq;
+	if (!list_empty(&q->request_freelist[rw])) {
+		rq = blkdev_free_rq(&q->request_freelist[rw]);
+		list_del(&rq->table);
+		rq->rq_status = RQ_ACTIVE;
+		rq->special = NULL;
+		rq->q = q;
 	}
 
-	return NULL;
-
-got_rq:
-	list_del(&rq->table);
-	rq->free_list = list;
-	rq->rq_status = RQ_ACTIVE;
-	rq->special = NULL;
-	rq->q = q;
 	return rq;
 }
 
@@ -581,40 +567,42 @@
 
 /*
  * add-request adds a request to the linked list.
- * It disables interrupts (acquires the request spinlock) so that it can muck
- * with the request-lists in peace. Thus it should be called with no spinlocks
- * held.
+ * io_request_lock is held and interrupts disabled, as we muck with the
+ * request queue list.
  *
  * By this point, req->cmd is always either READ/WRITE, never READA,
  * which is important for drive_stat_acct() above.
  */
-
 static inline void add_request(request_queue_t * q, struct request * req,
-			       struct list_head *head, int lat)
+			       struct list_head *insert_here)
 {
 	int major;
 
 	drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1);
 
+	if (!q->plugged && q->head_active && insert_here == &q->queue_head) {
+		spin_unlock_irq(&io_request_lock);
+		BUG();
+	}
+
 	/*
-	 * let selected elevator insert the request
+	 * elevator indicated where it wants this request to be
+	 * inserted at elevator_merge time
 	 */
-	q->elevator.elevator_fn(req, &q->elevator, &q->queue_head, head, lat);
+	list_add(&req->queue, insert_here);
 
-        /*
-	 * FIXME(eric) I don't understand why there is a need for this
-	 * special case code.  It clearly doesn't fit any more with
-	 * the new queueing architecture, and it got added in 2.3.10.
-	 * I am leaving this in here until I hear back from the COMPAQ
-	 * people.
-         */
 	major = MAJOR(req->rq_dev);
-	if (major >= COMPAQ_SMART2_MAJOR+0 && major <= COMPAQ_SMART2_MAJOR+7)
-		(q->request_fn)(q);
-	if (major >= COMPAQ_CISS_MAJOR+0 && major <= COMPAQ_CISS_MAJOR+7)
-                (q->request_fn)(q);
 	if (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7)
-		(q->request_fn)(q);
+		q->request_fn(q);
+}
+
+void inline blk_refill_freelist(request_queue_t *q, int rw)
+{
+	if (q->pending_free[rw]) {
+		list_splice(&q->pending_freelist[rw], &q->request_freelist[rw]);
+		INIT_LIST_HEAD(&q->pending_freelist[rw]);
+		q->pending_free[rw] = 0;
+	}
 }
 
 /*
@@ -622,15 +610,34 @@
  */
 void inline blkdev_release_request(struct request *req)
 {
+	request_queue_t *q = req->q;
+	int rw = req->cmd;
+
 	req->rq_status = RQ_INACTIVE;
+	req->q = NULL;
 
 	/*
-	 * Request may not have originated from ll_rw_blk
+	 * Request may not have originated from ll_rw_blk. if not,
+	 * asumme it has free buffers and check waiters
 	 */
-	if (req->free_list) {
-		list_add(&req->table, req->free_list);
-		req->free_list = NULL;
-		wake_up(&req->q->wait_for_request);
+	if (q) {
+		/*
+		 * we've released enough buffers to start I/O again
+		 */
+		if (waitqueue_active(&blk_buffers_wait)
+		    && atomic_read(&queued_sectors) < low_queued_sectors)
+			wake_up(&blk_buffers_wait);
+
+		/*
+		 * Add to pending free list and batch wakeups
+		 */
+		list_add(&req->table, &q->pending_freelist[rw]);
+
+		if (++q->pending_free[rw] >= batch_requests) {
+			int wake_up = q->pending_free[rw];
+			blk_refill_freelist(q, rw);
+			wake_up_nr(&q->wait_for_request, wake_up);
+		}
 	}
 }
 
@@ -658,9 +665,10 @@
 	 * will have been updated to the appropriate number,
 	 * and we shouldn't do it here too.
 	 */
-	if(!(q->merge_requests_fn)(q, req, next, max_segments))
+	if (!q->merge_requests_fn(q, req, next, max_segments))
 		return;
 
+	q->elevator.elevator_merge_req_fn(req, next);
 	req->bhtail->b_reqnext = next->bh;
 	req->bhtail = next->bhtail;
 	req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
@@ -699,7 +707,7 @@
 	int max_segments = MAX_SEGMENTS;
 	struct request * req = NULL, *freereq = NULL;
 	int rw_ahead, max_sectors, el_ret;
-	struct list_head *head;
+	struct list_head *head, *insert_here;
 	int latency;
 	elevator_t *elevator = &q->elevator;
 
@@ -713,6 +721,7 @@
 			rw = READ;	/* drop into READ */
 		case READ:
 		case WRITE:
+			latency = elevator_request_latency(elevator, rw);
 			break;
 		default:
 			BUG();
@@ -741,38 +750,33 @@
 	 */
 	max_sectors = get_max_sectors(bh->b_rdev);
 
-	latency = elevator_request_latency(elevator, rw);
-
+again:
+	head = &q->queue_head;
 	/*
 	 * Now we acquire the request spinlock, we have to be mega careful
 	 * not to schedule or do something nonatomic
 	 */
-again:
 	spin_lock_irq(&io_request_lock);
 
-	/*
-	 * skip first entry, for devices with active queue head
-	 */
-	head = &q->queue_head;
-	if (q->head_active && !q->plugged)
-		head = head->next;
-
+	insert_here = head->prev;
 	if (list_empty(head)) {
 		q->plug_device_fn(q, bh->b_rdev); /* is atomic */
 		goto get_rq;
-	}
+	} else if (q->head_active && !q->plugged)
+		head = head->next;
 
-	el_ret = elevator->elevator_merge_fn(q, &req, bh, rw,
-					     &max_sectors, &max_segments);
+	el_ret = elevator->elevator_merge_fn(q, &req, head, bh, rw,
+					     max_sectors, max_segments);
 	switch (el_ret) {
 
 		case ELEVATOR_BACK_MERGE:
 			if (!q->back_merge_fn(q, req, bh, max_segments))
 				break;
+			elevator->elevator_merge_cleanup_fn(q, req, count);
 			req->bhtail->b_reqnext = bh;
 			req->bhtail = bh;
 			req->nr_sectors = req->hard_nr_sectors += count;
-			req->e = elevator;
+			blk_started_io(count);
 			drive_stat_acct(req->rq_dev, req->cmd, count, 0);
 			attempt_back_merge(q, req, max_sectors, max_segments);
 			goto out;
@@ -780,20 +784,29 @@
 		case ELEVATOR_FRONT_MERGE:
 			if (!q->front_merge_fn(q, req, bh, max_segments))
 				break;
+			elevator->elevator_merge_cleanup_fn(q, req, count);
 			bh->b_reqnext = req->bh;
 			req->bh = bh;
 			req->buffer = bh->b_data;
 			req->current_nr_sectors = count;
 			req->sector = req->hard_sector = sector;
 			req->nr_sectors = req->hard_nr_sectors += count;
-			req->e = elevator;
+			blk_started_io(count);
 			drive_stat_acct(req->rq_dev, req->cmd, count, 0);
 			attempt_front_merge(q, head, req, max_sectors, max_segments);
 			goto out;
+
 		/*
 		 * elevator says don't/can't merge. get new request
 		 */
 		case ELEVATOR_NO_MERGE:
+			/*
+			 * use elevator hints as to where to insert the
+			 * request. if no hints, just add it to the back
+			 * of the queue
+			 */
+			if (req)
+				insert_here = &req->queue;
 			break;
 
 		default:
@@ -802,10 +815,9 @@
 	}
 		
 	/*
-	 * Grab a free request from the freelist. Read first try their
-	 * own queue - if that is empty, we steal from the write list.
-	 * Writes must block if the write list is empty, and read aheads
-	 * are not crucial.
+	 * Grab a free request from the freelist - if that is empty, check
+	 * if we are doing read ahead and abort instead of blocking for
+	 * a free slot.
 	 */
 get_rq:
 	if (freereq) {
@@ -821,6 +833,7 @@
 	}
 
 /* fill up the request-info, and add it to the queue */
+	req->elevator_sequence = latency;
 	req->cmd = rw;
 	req->errors = 0;
 	req->hard_sector = req->sector = sector;
@@ -833,13 +846,13 @@
 	req->bh = bh;
 	req->bhtail = bh;
 	req->rq_dev = bh->b_rdev;
-	req->e = elevator;
-	add_request(q, req, head, latency);
+	blk_started_io(count);
+	add_request(q, req, insert_here);
 out:
-	if (!q->plugged)
-		(q->request_fn)(q);
 	if (freereq)
 		blkdev_release_request(freereq);
+	if (!q->plugged)
+		q->request_fn(q);
 	spin_unlock_irq(&io_request_lock);
 	return 0;
 end_io:
@@ -886,13 +899,13 @@
 	int major = MAJOR(bh->b_rdev);
 	request_queue_t *q;
 
-	if (!bh->b_end_io) BUG();
+	if (!bh->b_end_io)
+		BUG();
+
 	if (blk_size[major]) {
 		unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;
-		unsigned int sector, count;
-
-		count = bh->b_size >> 9;
-		sector = bh->b_rsector;
+		unsigned long sector = bh->b_rsector;
+		unsigned int count = bh->b_size >> 9;
 
 		if (maxsector < count || maxsector - count < sector) {
 			bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped);
@@ -903,7 +916,7 @@
 				   when mounting a device. */
 				printk(KERN_INFO
 				       "attempt to access beyond end of device\n");
-				printk(KERN_INFO "%s: rw=%d, want=%d, limit=%d\n",
+				printk(KERN_INFO "%s: rw=%d, want=%ld, limit=%d\n",
 				       kdevname(bh->b_rdev), rw,
 				       (sector + count)>>1,
 				       blk_size[major][MINOR(bh->b_rdev)]);
@@ -930,15 +943,13 @@
 			buffer_IO_error(bh);
 			break;
 		}
-
-	}
-	while (q->make_request_fn(q, rw, bh));
+	} while (q->make_request_fn(q, rw, bh));
 }
 
 
 /**
  * submit_bh: submit a buffer_head to the block device later for I/O
- * @rw: whether to %READ or %WRITE, or mayve to %READA (read ahead)
+ * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead)
  * @bh: The &struct buffer_head which describes the I/O
  *
  * submit_bh() is very similar in purpose to generic_make_request(), and
@@ -961,7 +972,7 @@
 	 * further remap this.
 	 */
 	bh->b_rdev = bh->b_dev;
-	bh->b_rsector = bh->b_blocknr * (bh->b_size>>9);
+	bh->b_rsector = bh->b_blocknr * (bh->b_size >> 9);
 
 	generic_make_request(rw, bh);
 
@@ -1021,6 +1032,9 @@
 	int correct_size;
 	int i;
 
+	if (!nr)
+		return;
+
 	major = MAJOR(bhs[0]->b_dev);
 
 	/* Determine correct block size for this device. */
@@ -1033,9 +1047,8 @@
 
 	/* Verify requested block sizes. */
 	for (i = 0; i < nr; i++) {
-		struct buffer_head *bh;
-		bh = bhs[i];
-		if (bh->b_size != correct_size) {
+		struct buffer_head *bh = bhs[i];
+		if (bh->b_size % correct_size) {
 			printk(KERN_NOTICE "ll_rw_block: device %s: "
 			       "only %d-char blocks implemented (%u)\n",
 			       kdevname(bhs[0]->b_dev),
@@ -1051,8 +1064,17 @@
 	}
 
 	for (i = 0; i < nr; i++) {
-		struct buffer_head *bh;
-		bh = bhs[i];
+		struct buffer_head *bh = bhs[i];
+
+		/*
+		 * don't lock any more buffers if we are above the high
+		 * water mark. instead start I/O on the queued stuff.
+		 */
+		if (atomic_read(&queued_sectors) >= high_queued_sectors) {
+			run_task_queue(&tq_disk);
+			wait_event(blk_buffers_wait,
+			 atomic_read(&queued_sectors) < low_queued_sectors);
+		}
 
 		/* Only one thread can actually submit the I/O. */
 		if (test_and_set_bit(BH_Lock, &bh->b_state))
@@ -1096,12 +1118,25 @@
 extern int stram_device_init (void);
 #endif
 
-/*
- * First step of what used to be end_request
+
+/**
+ * end_that_request_first - end I/O on one buffer.
+ * @req:      the request being processed
+ * @uptodate: 0 for I/O error
+ * @name:     the name printed for an I/O error
  *
- * 0 means continue with end_that_request_last,
- * 1 means we are done
- */
+ * Description:
+ *     Ends I/O on the first buffer attached to @req, and sets it up
+ *     for the next buffer_head (if any) in the cluster.
+ *     
+ * Return:
+ *     0 - we are done with this request, call end_that_request_last()
+ *     1 - still buffers pending for this request
+ *
+ * Caveat: 
+ *     Drivers implementing their own end_request handling must call
+ *     blk_finished_io() appropriately.
+ **/
 
 int end_that_request_first (struct request *req, int uptodate, char *name)
 {
@@ -1115,6 +1150,7 @@
 
 	if ((bh = req->bh) != NULL) {
 		nsect = bh->b_size >> 9;
+		blk_finished_io(nsect);
 		req->bh = bh->b_reqnext;
 		bh->b_reqnext = NULL;
 		bh->b_end_io(bh, uptodate);
@@ -1138,19 +1174,18 @@
 
 void end_that_request_last(struct request *req)
 {
-	if (req->e) {
-		printk("end_that_request_last called with non-dequeued req\n");
-		BUG();
-	}
 	if (req->sem != NULL)
 		up(req->sem);
 
 	blkdev_release_request(req);
 }
 
+#define MB(kb)	((kb) << 10)
+
 int __init blk_dev_init(void)
 {
 	struct blk_dev_struct *dev;
+	int total_ram;
 
 	request_cachep = kmem_cache_create("blkdev_requests",
 					   sizeof(struct request),
@@ -1165,6 +1200,44 @@
 	memset(ro_bits,0,sizeof(ro_bits));
 	memset(max_readahead, 0, sizeof(max_readahead));
 	memset(max_sectors, 0, sizeof(max_sectors));
+
+	atomic_set(&queued_sectors, 0);
+	total_ram = nr_free_pages() << (PAGE_SHIFT - 10);
+
+	/*
+	 * Try to keep 128MB max hysteris. If not possible,
+	 * use half of RAM
+	 */
+	high_queued_sectors = (total_ram * 2) / 3;
+	low_queued_sectors = high_queued_sectors / 3;
+	if (high_queued_sectors - low_queued_sectors > MB(128))
+		low_queued_sectors = high_queued_sectors - MB(128);
+
+
+	/*
+	 * make it sectors (512b)
+	 */
+	high_queued_sectors <<= 1;
+	low_queued_sectors <<= 1;
+
+	/*
+	 * Scale free request slots per queue too
+	 */
+	total_ram = (total_ram + MB(32) - 1) & ~(MB(32) - 1);
+	if ((queue_nr_requests = total_ram >> 9) > QUEUE_NR_REQUESTS)
+		queue_nr_requests = QUEUE_NR_REQUESTS;
+
+	/*
+	 * adjust batch frees according to queue length, with upper limit
+	 */
+	if ((batch_requests = queue_nr_requests >> 3) > 32)
+		batch_requests = 32;
+
+	printk("block: queued sectors max/low %dkB/%dkB, %d slots per queue\n",
+						high_queued_sectors / 2,
+						low_queued_sectors / 2,
+						queue_nr_requests);
+
 #ifdef CONFIG_AMIGA_Z2RAM
 	z2_init();
 #endif
@@ -1268,9 +1341,6 @@
 #ifdef CONFIG_SUN_JSFLASH
 	jsfd_init();
 #endif
-#ifdef CONFIG_BLK_DEV_LVM
-	lvm_init();
-#endif
 	return 0;
 };
 
@@ -1279,9 +1349,12 @@
 EXPORT_SYMBOL(end_that_request_last);
 EXPORT_SYMBOL(blk_init_queue);
 EXPORT_SYMBOL(blk_get_queue);
+EXPORT_SYMBOL(__blk_get_queue);
 EXPORT_SYMBOL(blk_cleanup_queue);
 EXPORT_SYMBOL(blk_queue_headactive);
 EXPORT_SYMBOL(blk_queue_pluggable);
 EXPORT_SYMBOL(blk_queue_make_request);
 EXPORT_SYMBOL(generic_make_request);
 EXPORT_SYMBOL(blkdev_release_request);
+EXPORT_SYMBOL(generic_unplug_device);
+EXPORT_SYMBOL(queued_sectors);
diff -u --recursive --new-file v2.4.0/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.4.0/linux/drivers/block/paride/pd.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/block/paride/pd.c	Mon Jan 15 13:08:15 2001
@@ -392,7 +392,6 @@
 
 	if (req->nr_segments < max_segments) {
 		req->nr_segments++;
-		q->elevator.nr_segments++;
 		return 1;
 	}
 	return 0;
@@ -432,7 +431,6 @@
 	if (total_segments > max_segments)
 		return 0;
 
-	q->elevator.nr_segments -= same_segment;
 	req->nr_segments = total_segments;
 	return 1;
 }
diff -u --recursive --new-file v2.4.0/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
--- v2.4.0/linux/drivers/block/paride/pf.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/block/paride/pf.c	Mon Jan 15 13:08:15 2001
@@ -346,7 +346,6 @@
 
 	if (req->nr_segments < max_segments) {
 		req->nr_segments++;
-		q->elevator.nr_segments++;
 		return 1;
 	}
 	return 0;
@@ -386,7 +385,6 @@
 	if (total_segments > max_segments)
 		return 0;
 
-	q->elevator.nr_segments -= same_segment;
 	req->nr_segments = total_segments;
 	return 1;
 }
diff -u --recursive --new-file v2.4.0/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.4.0/linux/drivers/cdrom/cdrom.c	Sat Dec 30 18:16:13 2000
+++ linux/drivers/cdrom/cdrom.c	Sun Jan 28 13:37:50 2001
@@ -295,11 +295,11 @@
 
 /* These are used to simplify getting data in from and back to user land */
 #define IOCTL_IN(arg, type, in)					\
-	if (copy_from_user(&in, (type *) arg, sizeof in))	\
+	if (copy_from_user(&(in), (type *) (arg), sizeof (in)))	\
 		return -EFAULT;
 
 #define IOCTL_OUT(arg, type, out) \
-	if (copy_to_user((type *) arg, &out, sizeof out))	\
+	if (copy_to_user((type *) (arg), &(out), sizeof (out)))	\
 		return -EFAULT;
 
 /* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in
diff -u --recursive --new-file v2.4.0/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c
--- v2.4.0/linux/drivers/char/agp/agpgart_be.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/char/agp/agpgart_be.c	Sun Jan 28 13:28:09 2001
@@ -1384,9 +1384,11 @@
 	aper_size_info_8 *previous_size;
 
 	previous_size = A_SIZE_8(agp_bridge.previous_size);
-	pci_write_config_dword(agp_bridge.dev, VIA_ATTBASE, 0);
 	pci_write_config_byte(agp_bridge.dev, VIA_APSIZE,
 			      previous_size->size_value);
+	/* Do not disable by writing 0 to VIA_ATTBASE, it screws things up
+	 * during reinitialization.
+	 */
 }
 
 static void via_tlbflush(agp_memory * mem)
@@ -2373,9 +2375,10 @@
 			if (i810_dev == NULL) {
 				printk(KERN_ERR PFX "agpgart: Detected an "
 				       "Intel i815, but could not find the"
-				       " secondary device.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return -ENODEV;
+				       " secondary device.\n"
+				       "Assuming user has added an external AGP"
+				       " card\n");
+				break;
 			}
 			printk(KERN_INFO PFX "agpgart: Detected an Intel i815 "
 			       "Chipset.\n");
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/Config.in linux/drivers/char/drm/Config.in
--- v2.4.0/linux/drivers/char/drm/Config.in	Tue Aug  8 09:27:33 2000
+++ linux/drivers/char/drm/Config.in	Fri Jan 19 13:34:28 2001
@@ -9,7 +9,8 @@
 if [ "$CONFIG_DRM" != "n" ]; then
     tristate '  3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX
     tristate '  3dlabs GMX 2000' CONFIG_DRM_GAMMA
-    tristate '  ATI Rage 128' CONFIG_DRM_R128
+    dep_tristate '  ATI Rage 128' CONFIG_DRM_R128 $CONFIG_AGP
+    dep_tristate '  ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
     dep_tristate '  Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
     dep_tristate '  Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP
 fi
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/Makefile linux/drivers/char/drm/Makefile
--- v2.4.0/linux/drivers/char/drm/Makefile	Thu Jan  4 13:07:01 2001
+++ linux/drivers/char/drm/Makefile	Fri Jan 19 13:35:02 2001
@@ -42,16 +42,18 @@
  endif
 endif
 
-gamma-objs := gamma_drv.o gamma_dma.o
-tdfx-objs  := tdfx_drv.o                tdfx_context.o
-r128-objs  := r128_drv.o  r128_cce.o    r128_context.o r128_bufs.o r128_state.o
-ffb-objs   := ffb_drv.o                 ffb_context.o
-mga-objs   := mga_drv.o   mga_dma.o     mga_context.o  mga_bufs.o  mga_state.o
-i810-objs  := i810_drv.o  i810_dma.o    i810_context.o i810_bufs.o
+gamma-objs  := gamma_drv.o  gamma_dma.o
+tdfx-objs   := tdfx_drv.o                 tdfx_context.o
+r128-objs   := r128_drv.o   r128_cce.o    r128_context.o r128_bufs.o r128_state.o
+ffb-objs    := ffb_drv.o                  ffb_context.o
+mga-objs    := mga_drv.o    mga_dma.o     mga_context.o  mga_bufs.o  mga_state.o
+i810-objs   := i810_drv.o   i810_dma.o    i810_context.o i810_bufs.o
+radeon-objs := radeon_drv.o radeon_cp.o   radeon_context.o radeon_bufs.o radeon_state.o
 
 obj-$(CONFIG_DRM_GAMMA) += gamma.o
 obj-$(CONFIG_DRM_TDFX)  += tdfx.o
 obj-$(CONFIG_DRM_R128)  += r128.o
+obj-$(CONFIG_DRM_RADEON)+= radeon.o
 obj-$(CONFIG_DRM_FFB)   += ffb.o
 obj-$(CONFIG_DRM_MGA)   += mga.o
 obj-$(CONFIG_DRM_I810)  += i810.o
@@ -95,6 +97,9 @@
 
 r128.o: $(r128-objs) $(lib)
 	$(LD) -r -o $@ $(r128-objs) $(lib)
+
+radeon.o: $(radeon-objs) $(lib)
+	$(LD) -r -o $@ $(radeon-objs) $(lib)
 
 ffb.o: $(ffb-objs) $(lib)
 	$(LD) -r -o $@ $(ffb-objs) $(lib)
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/drm.h linux/drivers/char/drm/drm.h
--- v2.4.0/linux/drivers/char/drm/drm.h	Thu Jan  4 15:25:55 2001
+++ linux/drivers/char/drm/drm.h	Fri Jan 19 21:38:59 2001
@@ -83,6 +83,7 @@
 #include "mga_drm.h"
 #include "i810_drm.h"
 #include "r128_drm.h"
+#include "radeon_drm.h"
 #ifdef CONFIG_DRM_SIS
 #include "sis_drm.h"
 #endif
@@ -298,100 +299,116 @@
 	unsigned short id_device;
 } drm_agp_info_t;
 
-#define DRM_IOCTL_BASE	     'd'
-#define DRM_IO(nr)	     _IO(DRM_IOCTL_BASE,nr)
-#define DRM_IOR(nr,size)     _IOR(DRM_IOCTL_BASE,nr,size)
-#define DRM_IOW(nr,size)     _IOW(DRM_IOCTL_BASE,nr,size)
-#define DRM_IOWR(nr,size)    _IOWR(DRM_IOCTL_BASE,nr,size)
-
-
-#define DRM_IOCTL_VERSION    DRM_IOWR(0x00, drm_version_t)
-#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
-#define DRM_IOCTL_GET_MAGIC  DRM_IOR( 0x02, drm_auth_t)
-#define DRM_IOCTL_IRQ_BUSID  DRM_IOWR(0x03, drm_irq_busid_t)
-
-#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
-#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
-#define DRM_IOCTL_BLOCK	     DRM_IOWR(0x12, drm_block_t)
-#define DRM_IOCTL_UNBLOCK    DRM_IOWR(0x13, drm_block_t)
-#define DRM_IOCTL_CONTROL    DRM_IOW( 0x14, drm_control_t)
-#define DRM_IOCTL_ADD_MAP    DRM_IOWR(0x15, drm_map_t)
-#define DRM_IOCTL_ADD_BUFS   DRM_IOWR(0x16, drm_buf_desc_t)
-#define DRM_IOCTL_MARK_BUFS  DRM_IOW( 0x17, drm_buf_desc_t)
-#define DRM_IOCTL_INFO_BUFS  DRM_IOWR(0x18, drm_buf_info_t)
-#define DRM_IOCTL_MAP_BUFS   DRM_IOWR(0x19, drm_buf_map_t)
-#define DRM_IOCTL_FREE_BUFS  DRM_IOW( 0x1a, drm_buf_free_t)
-
-#define DRM_IOCTL_ADD_CTX    DRM_IOWR(0x20, drm_ctx_t)
-#define DRM_IOCTL_RM_CTX     DRM_IOWR(0x21, drm_ctx_t)
-#define DRM_IOCTL_MOD_CTX    DRM_IOW( 0x22, drm_ctx_t)
-#define DRM_IOCTL_GET_CTX    DRM_IOWR(0x23, drm_ctx_t)
-#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, drm_ctx_t)
-#define DRM_IOCTL_NEW_CTX    DRM_IOW( 0x25, drm_ctx_t)
-#define DRM_IOCTL_RES_CTX    DRM_IOWR(0x26, drm_ctx_res_t)
-#define DRM_IOCTL_ADD_DRAW   DRM_IOWR(0x27, drm_draw_t)
-#define DRM_IOCTL_RM_DRAW    DRM_IOWR(0x28, drm_draw_t)
-#define DRM_IOCTL_DMA	     DRM_IOWR(0x29, drm_dma_t)
-#define DRM_IOCTL_LOCK	     DRM_IOW( 0x2a, drm_lock_t)
-#define DRM_IOCTL_UNLOCK     DRM_IOW( 0x2b, drm_lock_t)
-#define DRM_IOCTL_FINISH     DRM_IOW( 0x2c, drm_lock_t)
-
-#define DRM_IOCTL_AGP_ACQUIRE DRM_IO(  0x30)
-#define DRM_IOCTL_AGP_RELEASE DRM_IO(  0x31)
-#define DRM_IOCTL_AGP_ENABLE  DRM_IOW( 0x32, drm_agp_mode_t)
-#define DRM_IOCTL_AGP_INFO    DRM_IOR( 0x33, drm_agp_info_t)
-#define DRM_IOCTL_AGP_ALLOC   DRM_IOWR(0x34, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_FREE    DRM_IOW( 0x35, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_BIND    DRM_IOW( 0x36, drm_agp_binding_t)
-#define DRM_IOCTL_AGP_UNBIND  DRM_IOW( 0x37, drm_agp_binding_t)
+#define DRM_IOCTL_BASE			'd'
+#define DRM_IO(nr)			_IO(DRM_IOCTL_BASE,nr)
+#define DRM_IOR(nr,size)		_IOR(DRM_IOCTL_BASE,nr,size)
+#define DRM_IOW(nr,size)		_IOW(DRM_IOCTL_BASE,nr,size)
+#define DRM_IOWR(nr,size)		_IOWR(DRM_IOCTL_BASE,nr,size)
+
+
+#define DRM_IOCTL_VERSION		DRM_IOWR(0x00, drm_version_t)
+#define DRM_IOCTL_GET_UNIQUE		DRM_IOWR(0x01, drm_unique_t)
+#define DRM_IOCTL_GET_MAGIC		DRM_IOR( 0x02, drm_auth_t)
+#define DRM_IOCTL_IRQ_BUSID		DRM_IOWR(0x03, drm_irq_busid_t)
+
+#define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, drm_unique_t)
+#define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, drm_auth_t)
+#define DRM_IOCTL_BLOCK			DRM_IOWR(0x12, drm_block_t)
+#define DRM_IOCTL_UNBLOCK		DRM_IOWR(0x13, drm_block_t)
+#define DRM_IOCTL_CONTROL		DRM_IOW( 0x14, drm_control_t)
+#define DRM_IOCTL_ADD_MAP		DRM_IOWR(0x15, drm_map_t)
+#define DRM_IOCTL_ADD_BUFS		DRM_IOWR(0x16, drm_buf_desc_t)
+#define DRM_IOCTL_MARK_BUFS		DRM_IOW( 0x17, drm_buf_desc_t)
+#define DRM_IOCTL_INFO_BUFS		DRM_IOWR(0x18, drm_buf_info_t)
+#define DRM_IOCTL_MAP_BUFS		DRM_IOWR(0x19, drm_buf_map_t)
+#define DRM_IOCTL_FREE_BUFS		DRM_IOW( 0x1a, drm_buf_free_t)
+
+#define DRM_IOCTL_ADD_CTX		DRM_IOWR(0x20, drm_ctx_t)
+#define DRM_IOCTL_RM_CTX		DRM_IOWR(0x21, drm_ctx_t)
+#define DRM_IOCTL_MOD_CTX		DRM_IOW( 0x22, drm_ctx_t)
+#define DRM_IOCTL_GET_CTX		DRM_IOWR(0x23, drm_ctx_t)
+#define DRM_IOCTL_SWITCH_CTX		DRM_IOW( 0x24, drm_ctx_t)
+#define DRM_IOCTL_NEW_CTX		DRM_IOW( 0x25, drm_ctx_t)
+#define DRM_IOCTL_RES_CTX		DRM_IOWR(0x26, drm_ctx_res_t)
+#define DRM_IOCTL_ADD_DRAW		DRM_IOWR(0x27, drm_draw_t)
+#define DRM_IOCTL_RM_DRAW		DRM_IOWR(0x28, drm_draw_t)
+#define DRM_IOCTL_DMA			DRM_IOWR(0x29, drm_dma_t)
+#define DRM_IOCTL_LOCK			DRM_IOW( 0x2a, drm_lock_t)
+#define DRM_IOCTL_UNLOCK		DRM_IOW( 0x2b, drm_lock_t)
+#define DRM_IOCTL_FINISH		DRM_IOW( 0x2c, drm_lock_t)
+
+#define DRM_IOCTL_AGP_ACQUIRE		DRM_IO(  0x30)
+#define DRM_IOCTL_AGP_RELEASE		DRM_IO(  0x31)
+#define DRM_IOCTL_AGP_ENABLE		DRM_IOW( 0x32, drm_agp_mode_t)
+#define DRM_IOCTL_AGP_INFO		DRM_IOR( 0x33, drm_agp_info_t)
+#define DRM_IOCTL_AGP_ALLOC		DRM_IOWR(0x34, drm_agp_buffer_t)
+#define DRM_IOCTL_AGP_FREE		DRM_IOW( 0x35, drm_agp_buffer_t)
+#define DRM_IOCTL_AGP_BIND		DRM_IOW( 0x36, drm_agp_binding_t)
+#define DRM_IOCTL_AGP_UNBIND		DRM_IOW( 0x37, drm_agp_binding_t)
 
 /* Mga specific ioctls */
-#define DRM_IOCTL_MGA_INIT    DRM_IOW( 0x40, drm_mga_init_t)
-#define DRM_IOCTL_MGA_SWAP    DRM_IOW( 0x41, drm_mga_swap_t)
-#define DRM_IOCTL_MGA_CLEAR   DRM_IOW( 0x42, drm_mga_clear_t)
-#define DRM_IOCTL_MGA_ILOAD   DRM_IOW( 0x43, drm_mga_iload_t)
-#define DRM_IOCTL_MGA_VERTEX  DRM_IOW( 0x44, drm_mga_vertex_t)
-#define DRM_IOCTL_MGA_FLUSH   DRM_IOW( 0x45, drm_lock_t )
-#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
-#define DRM_IOCTL_MGA_BLIT    DRM_IOW( 0x47, drm_mga_blit_t)
+#define DRM_IOCTL_MGA_INIT		DRM_IOW( 0x40, drm_mga_init_t)
+#define DRM_IOCTL_MGA_SWAP		DRM_IOW( 0x41, drm_mga_swap_t)
+#define DRM_IOCTL_MGA_CLEAR		DRM_IOW( 0x42, drm_mga_clear_t)
+#define DRM_IOCTL_MGA_ILOAD		DRM_IOW( 0x43, drm_mga_iload_t)
+#define DRM_IOCTL_MGA_VERTEX		DRM_IOW( 0x44, drm_mga_vertex_t)
+#define DRM_IOCTL_MGA_FLUSH		DRM_IOW( 0x45, drm_lock_t )
+#define DRM_IOCTL_MGA_INDICES		DRM_IOW( 0x46, drm_mga_indices_t)
+#define DRM_IOCTL_MGA_BLIT		DRM_IOW( 0x47, drm_mga_blit_t)
 
 /* I810 specific ioctls */
-#define DRM_IOCTL_I810_INIT    DRM_IOW( 0x40, drm_i810_init_t)
-#define DRM_IOCTL_I810_VERTEX  DRM_IOW( 0x41, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_CLEAR   DRM_IOW( 0x42, drm_i810_clear_t)
-#define DRM_IOCTL_I810_FLUSH   DRM_IO ( 0x43)
-#define DRM_IOCTL_I810_GETAGE  DRM_IO ( 0x44)
-#define DRM_IOCTL_I810_GETBUF  DRM_IOWR(0x45, drm_i810_dma_t)
-#define DRM_IOCTL_I810_SWAP    DRM_IO ( 0x46)
-#define DRM_IOCTL_I810_COPY    DRM_IOW( 0x47, drm_i810_copy_t)
-#define DRM_IOCTL_I810_DOCOPY  DRM_IO ( 0x48)
+#define DRM_IOCTL_I810_INIT		DRM_IOW( 0x40, drm_i810_init_t)
+#define DRM_IOCTL_I810_VERTEX		DRM_IOW( 0x41, drm_i810_vertex_t)
+#define DRM_IOCTL_I810_CLEAR		DRM_IOW( 0x42, drm_i810_clear_t)
+#define DRM_IOCTL_I810_FLUSH		DRM_IO(  0x43)
+#define DRM_IOCTL_I810_GETAGE		DRM_IO(  0x44)
+#define DRM_IOCTL_I810_GETBUF		DRM_IOWR(0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP		DRM_IO(  0x46)
+#define DRM_IOCTL_I810_COPY		DRM_IOW( 0x47, drm_i810_copy_t)
+#define DRM_IOCTL_I810_DOCOPY		DRM_IO(  0x48)
 
 /* Rage 128 specific ioctls */
-#define DRM_IOCTL_R128_INIT	 DRM_IOW( 0x40, drm_r128_init_t)
-#define DRM_IOCTL_R128_CCE_START DRM_IO(  0x41)
-#define DRM_IOCTL_R128_CCE_STOP	 DRM_IOW( 0x42, drm_r128_cce_stop_t)
-#define DRM_IOCTL_R128_CCE_RESET DRM_IO(  0x43)
-#define DRM_IOCTL_R128_CCE_IDLE	 DRM_IO(  0x44)
-#define DRM_IOCTL_R128_RESET	 DRM_IO(  0x46)
-#define DRM_IOCTL_R128_SWAP	 DRM_IO(  0x47)
-#define DRM_IOCTL_R128_CLEAR	 DRM_IOW( 0x48, drm_r128_clear_t)
-#define DRM_IOCTL_R128_VERTEX	 DRM_IOW( 0x49, drm_r128_vertex_t)
-#define DRM_IOCTL_R128_INDICES	 DRM_IOW( 0x4a, drm_r128_indices_t)
-#define DRM_IOCTL_R128_BLIT	 DRM_IOW( 0x4b, drm_r128_blit_t)
-#define DRM_IOCTL_R128_DEPTH	 DRM_IOW( 0x4c, drm_r128_depth_t)
-#define DRM_IOCTL_R128_STIPPLE	 DRM_IOW( 0x4d, drm_r128_stipple_t)
-#define DRM_IOCTL_R128_PACKET	 DRM_IOWR(0x4e, drm_r128_packet_t)
+#define DRM_IOCTL_R128_INIT		DRM_IOW( 0x40, drm_r128_init_t)
+#define DRM_IOCTL_R128_CCE_START	DRM_IO(  0x41)
+#define DRM_IOCTL_R128_CCE_STOP		DRM_IOW( 0x42, drm_r128_cce_stop_t)
+#define DRM_IOCTL_R128_CCE_RESET	DRM_IO(  0x43)
+#define DRM_IOCTL_R128_CCE_IDLE		DRM_IO(  0x44)
+#define DRM_IOCTL_R128_RESET		DRM_IO(  0x46)
+#define DRM_IOCTL_R128_SWAP		DRM_IO(  0x47)
+#define DRM_IOCTL_R128_CLEAR		DRM_IOW( 0x48, drm_r128_clear_t)
+#define DRM_IOCTL_R128_VERTEX		DRM_IOW( 0x49, drm_r128_vertex_t)
+#define DRM_IOCTL_R128_INDICES		DRM_IOW( 0x4a, drm_r128_indices_t)
+#define DRM_IOCTL_R128_BLIT		DRM_IOW( 0x4b, drm_r128_blit_t)
+#define DRM_IOCTL_R128_DEPTH		DRM_IOW( 0x4c, drm_r128_depth_t)
+#define DRM_IOCTL_R128_STIPPLE		DRM_IOW( 0x4d, drm_r128_stipple_t)
+#define DRM_IOCTL_R128_PACKET		DRM_IOWR(0x4e, drm_r128_packet_t)
+
+/* Radeon specific ioctls */
+#define DRM_IOCTL_RADEON_CP_INIT	DRM_IOW( 0x40, drm_radeon_init_t)
+#define DRM_IOCTL_RADEON_CP_START	DRM_IO(  0x41)
+#define DRM_IOCTL_RADEON_CP_STOP	DRM_IOW( 0x42, drm_radeon_cp_stop_t)
+#define DRM_IOCTL_RADEON_CP_RESET	DRM_IO(  0x43)
+#define DRM_IOCTL_RADEON_CP_IDLE	DRM_IO(  0x44)
+#define DRM_IOCTL_RADEON_RESET		DRM_IO(  0x45)
+#define DRM_IOCTL_RADEON_FULLSCREEN	DRM_IOW( 0x46, drm_radeon_fullscreen_t)
+#define DRM_IOCTL_RADEON_SWAP		DRM_IO(  0x47)
+#define DRM_IOCTL_RADEON_CLEAR		DRM_IOW( 0x48, drm_radeon_clear_t)
+#define DRM_IOCTL_RADEON_VERTEX		DRM_IOW( 0x49, drm_radeon_vertex_t)
+#define DRM_IOCTL_RADEON_INDICES	DRM_IOW( 0x4a, drm_radeon_indices_t)
+#define DRM_IOCTL_RADEON_BLIT		DRM_IOW( 0x4b, drm_radeon_blit_t)
+#define DRM_IOCTL_RADEON_STIPPLE	DRM_IOW( 0x4c, drm_radeon_stipple_t)
+#define DRM_IOCTL_RADEON_INDIRECT	DRM_IOWR(0x4d, drm_radeon_indirect_t)
 
 #ifdef CONFIG_DRM_SIS
 /* SiS specific ioctls */
-#define SIS_IOCTL_FB_ALLOC     DRM_IOWR( 0x44, drm_sis_mem_t)
-#define SIS_IOCTL_FB_FREE      DRM_IOW( 0x45, drm_sis_mem_t)
-#define SIS_IOCTL_AGP_INIT     DRM_IOWR( 0x53, drm_sis_agp_t)
-#define SIS_IOCTL_AGP_ALLOC    DRM_IOWR( 0x54, drm_sis_mem_t)
-#define SIS_IOCTL_AGP_FREE     DRM_IOW( 0x55, drm_sis_mem_t)
-#define SIS_IOCTL_FLIP         DRM_IOW( 0x48, drm_sis_flip_t)
-#define SIS_IOCTL_FLIP_INIT    DRM_IO( 0x49)
-#define SIS_IOCTL_FLIP_FINAL   DRM_IO( 0x50)
+#define SIS_IOCTL_FB_ALLOC		DRM_IOWR(0x44, drm_sis_mem_t)
+#define SIS_IOCTL_FB_FREE		DRM_IOW( 0x45, drm_sis_mem_t)
+#define SIS_IOCTL_AGP_INIT		DRM_IOWR(0x53, drm_sis_agp_t)
+#define SIS_IOCTL_AGP_ALLOC		DRM_IOWR(0x54, drm_sis_mem_t)
+#define SIS_IOCTL_AGP_FREE		DRM_IOW( 0x55, drm_sis_mem_t)
+#define SIS_IOCTL_FLIP			DRM_IOW( 0x48, drm_sis_flip_t)
+#define SIS_IOCTL_FLIP_INIT		DRM_IO(  0x49)
+#define SIS_IOCTL_FLIP_FINAL		DRM_IO(  0x50)
 #endif
 
 #endif
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/radeon_bufs.c linux/drivers/char/drm/radeon_bufs.c
--- v2.4.0/linux/drivers/char/drm/radeon_bufs.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/radeon_bufs.c	Fri Jan 19 13:34:08 2001
@@ -0,0 +1,298 @@
+/* radeon_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Kevin E. Martin <martin@valinux.com>
+ *          Rickard E. (Rik) Faith <faith@valinux.com>
+ *	    Jeff Hartmann <jhartmann@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include "drmP.h"
+#include "radeon_drv.h"
+#include "linux/un.h"
+
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+int radeon_addbufs_agp(struct inode *inode, struct file *filp,
+		       unsigned int cmd, unsigned long arg)
+{
+	drm_file_t       *priv = filp->private_data;
+	drm_device_t     *dev  = priv->dev;
+	drm_device_dma_t *dma  = dev->dma;
+	drm_buf_desc_t    request;
+	drm_buf_entry_t  *entry;
+	drm_buf_t        *buf;
+	unsigned long     offset;
+	unsigned long     agp_offset;
+	int               count;
+	int               order;
+	int               size;
+	int               alignment;
+	int               page_order;
+	int               total;
+	int               byte_count;
+	int               i;
+
+	if (!dma) return -EINVAL;
+
+	if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
+		return -EFAULT;
+
+	count      = request.count;
+	order      = drm_order(request.size);
+	size       = 1 << order;
+
+	alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
+	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+	total      = PAGE_SIZE << page_order;
+
+	byte_count = 0;
+	agp_offset = dev->agp->base + request.agp_start;
+
+	DRM_DEBUG("count:      %d\n",  count);
+	DRM_DEBUG("order:      %d\n",  order);
+	DRM_DEBUG("size:       %d\n",  size);
+	DRM_DEBUG("agp_offset: %ld\n", agp_offset);
+	DRM_DEBUG("alignment:  %d\n",  alignment);
+	DRM_DEBUG("page_order: %d\n",  page_order);
+	DRM_DEBUG("total:      %d\n",  total);
+
+	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
+	if (dev->queue_count) return -EBUSY; /* Not while in use */
+
+	spin_lock(&dev->count_lock);
+	if (dev->buf_use) {
+		spin_unlock(&dev->count_lock);
+		return -EBUSY;
+	}
+	atomic_inc(&dev->buf_alloc);
+	spin_unlock(&dev->count_lock);
+
+	down(&dev->struct_sem);
+	entry = &dma->bufs[order];
+	if (entry->buf_count) {
+		up(&dev->struct_sem);
+		atomic_dec(&dev->buf_alloc);
+		return -ENOMEM; /* May only call once for each order */
+	}
+
+	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+				   DRM_MEM_BUFS);
+	if (!entry->buflist) {
+		up(&dev->struct_sem);
+		atomic_dec(&dev->buf_alloc);
+		return -ENOMEM;
+	}
+	memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+	entry->buf_size   = size;
+	entry->page_order = page_order;
+	offset            = 0;
+
+	for (offset = 0;
+	     entry->buf_count < count;
+	     offset += alignment, ++entry->buf_count) {
+		buf          = &entry->buflist[entry->buf_count];
+		buf->idx     = dma->buf_count + entry->buf_count;
+		buf->total   = alignment;
+		buf->order   = order;
+		buf->used    = 0;
+		buf->offset  = (dma->byte_count + offset);
+		buf->address = (void *)(agp_offset + offset);
+		buf->next    = NULL;
+		buf->waiting = 0;
+		buf->pending = 0;
+		init_waitqueue_head(&buf->dma_wait);
+		buf->pid     = 0;
+
+		buf->dev_priv_size = sizeof(drm_radeon_buf_priv_t);
+		buf->dev_private   = drm_alloc(sizeof(drm_radeon_buf_priv_t),
+					       DRM_MEM_BUFS);
+		memset(buf->dev_private, 0, buf->dev_priv_size);
+
+#if DRM_DMA_HISTOGRAM
+		buf->time_queued     = 0;
+		buf->time_dispatched = 0;
+		buf->time_completed  = 0;
+		buf->time_freed      = 0;
+#endif
+
+		byte_count += PAGE_SIZE << page_order;
+
+		DRM_DEBUG("buffer %d @ %p\n",
+			  entry->buf_count, buf->address);
+	}
+
+	DRM_DEBUG("byte_count: %d\n", byte_count);
+
+	dma->buflist = drm_realloc(dma->buflist,
+				   dma->buf_count * sizeof(*dma->buflist),
+				   (dma->buf_count + entry->buf_count)
+				   * sizeof(*dma->buflist),
+				   DRM_MEM_BUFS);
+	for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
+		dma->buflist[i] = &entry->buflist[i - dma->buf_count];
+
+	dma->buf_count  += entry->buf_count;
+	dma->byte_count += byte_count;
+
+	drm_freelist_create(&entry->freelist, entry->buf_count);
+	for (i = 0; i < entry->buf_count; i++) {
+		drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
+	}
+
+	up(&dev->struct_sem);
+
+	request.count = entry->buf_count;
+	request.size  = size;
+
+	if (copy_to_user((drm_buf_desc_t *)arg, &request, sizeof(request)))
+		return -EFAULT;
+
+	dma->flags = _DRM_DMA_USE_AGP;
+
+	atomic_dec(&dev->buf_alloc);
+	return 0;
+}
+#endif
+
+int radeon_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
+		   unsigned long arg)
+{
+	drm_file_t		*priv		= filp->private_data;
+	drm_device_t		*dev		= priv->dev;
+	drm_radeon_private_t	*dev_priv	= dev->dev_private;
+	drm_buf_desc_t		request;
+
+	if (!dev_priv || dev_priv->is_pci) return -EINVAL;
+
+	if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
+		return -EFAULT;
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+	if (request.flags & _DRM_AGP_BUFFER)
+		return radeon_addbufs_agp(inode, filp, cmd, arg);
+	else
+#endif
+		return -EINVAL;
+}
+
+int radeon_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
+		   unsigned long arg)
+{
+	drm_file_t		*priv		= filp->private_data;
+	drm_device_t		*dev		= priv->dev;
+	drm_radeon_private_t	*dev_priv	= dev->dev_private;
+	drm_device_dma_t	*dma		= dev->dma;
+	int			 retcode	= 0;
+	const int		 zero		= 0;
+	unsigned long		 virtual;
+	unsigned long		 address;
+	drm_buf_map_t		 request;
+	int			 i;
+
+	if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL;
+
+	DRM_DEBUG("\n");
+
+	spin_lock(&dev->count_lock);
+	if (atomic_read(&dev->buf_alloc)) {
+		spin_unlock(&dev->count_lock);
+		return -EBUSY;
+	}
+	++dev->buf_use;		/* Can't allocate more after this call */
+	spin_unlock(&dev->count_lock);
+
+	if (copy_from_user(&request, (drm_buf_map_t *)arg, sizeof(request)))
+		return -EFAULT;
+
+	if (request.count >= dma->buf_count) {
+		if (dma->flags & _DRM_DMA_USE_AGP) {
+			drm_map_t *map;
+
+			map = dev_priv->buffers;
+			if (!map) {
+				retcode = -EINVAL;
+				goto done;
+			}
+
+			down(&current->mm->mmap_sem);
+			virtual = do_mmap(filp, 0, map->size,
+					  PROT_READ|PROT_WRITE,
+					  MAP_SHARED,
+					  (unsigned long)map->offset);
+			up(&current->mm->mmap_sem);
+		} else {
+			down(&current->mm->mmap_sem);
+			virtual = do_mmap(filp, 0, dma->byte_count,
+					  PROT_READ|PROT_WRITE, MAP_SHARED, 0);
+			up(&current->mm->mmap_sem);
+		}
+		if (virtual > -1024UL) {
+			/* Real error */
+			retcode = (signed long)virtual;
+			goto done;
+		}
+		request.virtual = (void *)virtual;
+
+		for (i = 0; i < dma->buf_count; i++) {
+			if (copy_to_user(&request.list[i].idx,
+					 &dma->buflist[i]->idx,
+					 sizeof(request.list[0].idx))) {
+				retcode = -EFAULT;
+				goto done;
+			}
+			if (copy_to_user(&request.list[i].total,
+					 &dma->buflist[i]->total,
+					 sizeof(request.list[0].total))) {
+				retcode = -EFAULT;
+				goto done;
+			}
+			if (copy_to_user(&request.list[i].used,
+					 &zero,
+					 sizeof(zero))) {
+				retcode = -EFAULT;
+				goto done;
+			}
+			address = virtual + dma->buflist[i]->offset;
+			if (copy_to_user(&request.list[i].address,
+					 &address,
+					 sizeof(address))) {
+				retcode = -EFAULT;
+				goto done;
+			}
+		}
+	}
+ done:
+	request.count = dma->buf_count;
+	DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
+
+	if (copy_to_user((drm_buf_map_t *)arg, &request, sizeof(request)))
+		return -EFAULT;
+
+	return retcode;
+}
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/radeon_context.c linux/drivers/char/drm/radeon_context.c
--- v2.4.0/linux/drivers/char/drm/radeon_context.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/radeon_context.c	Fri Jan 19 13:34:08 2001
@@ -0,0 +1,215 @@
+/* radeon_context.c -- IOCTLs for Radeon contexts -*- linux-c -*-
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Kevin E. Martin <martin@valinux.com>
+ *         Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "radeon_drv.h"
+
+extern drm_ctx_t radeon_res_ctx;
+
+static int radeon_alloc_queue(drm_device_t *dev)
+{
+	return drm_ctxbitmap_next(dev);
+}
+
+int radeon_context_switch(drm_device_t *dev, int old, int new)
+{
+        char        buf[64];
+
+        atomic_inc(&dev->total_ctx);
+
+        if (test_and_set_bit(0, &dev->context_flag)) {
+                DRM_ERROR("Reentering -- FIXME\n");
+                return -EBUSY;
+        }
+
+#if DRM_DMA_HISTOGRAM
+        dev->ctx_start = get_cycles();
+#endif
+
+        DRM_DEBUG("Context switch from %d to %d\n", old, new);
+
+        if (new == dev->last_context) {
+                clear_bit(0, &dev->context_flag);
+                return 0;
+        }
+
+        if (drm_flags & DRM_FLAG_NOCTX) {
+                radeon_context_switch_complete(dev, new);
+        } else {
+                sprintf(buf, "C %d %d\n", old, new);
+                drm_write_string(dev, buf);
+        }
+
+        return 0;
+}
+
+int radeon_context_switch_complete(drm_device_t *dev, int new)
+{
+        dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
+        dev->last_switch  = jiffies;
+
+        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+                DRM_ERROR("Lock isn't held after context switch\n");
+        }
+
+				/* If a context switch is ever initiated
+                                   when the kernel holds the lock, release
+                                   that lock here. */
+#if DRM_DMA_HISTOGRAM
+        atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
+                                                      - dev->ctx_start)]);
+
+#endif
+        clear_bit(0, &dev->context_flag);
+        wake_up(&dev->context_wait);
+
+        return 0;
+}
+
+
+int radeon_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+	drm_ctx_res_t	res;
+	drm_ctx_t	ctx;
+	int		i;
+
+	DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
+	if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
+		return -EFAULT;
+	if (res.count >= DRM_RESERVED_CONTEXTS) {
+		memset(&ctx, 0, sizeof(ctx));
+		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
+			ctx.handle = i;
+			if (copy_to_user(&res.contexts[i], &i, sizeof(i)))
+				return -EFAULT;
+		}
+	}
+	res.count = DRM_RESERVED_CONTEXTS;
+	if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
+		return -EFAULT;
+	return 0;
+}
+
+
+int radeon_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+	drm_file_t	*priv	= filp->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_ctx_t	ctx;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+	if ((ctx.handle = radeon_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
+				/* Skip kernel's context and get a new one. */
+		ctx.handle = radeon_alloc_queue(dev);
+	}
+	DRM_DEBUG("%d\n", ctx.handle);
+	if (ctx.handle == -1) {
+		DRM_DEBUG("Not enough free contexts.\n");
+				/* Should this return -EBUSY instead? */
+		return -ENOMEM;
+	}
+
+	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+		return -EFAULT;
+	return 0;
+}
+
+int radeon_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+	drm_ctx_t ctx;
+
+	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+		return -EFAULT;
+	if (ctx.flags==_DRM_CONTEXT_PRESERVED)
+		radeon_res_ctx.handle=ctx.handle;
+	return 0;
+}
+
+int radeon_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+	drm_ctx_t ctx;
+
+	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
+		return -EFAULT;
+	/* This is 0, because we don't hanlde any context flags */
+	ctx.flags = 0;
+	if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
+		return -EFAULT;
+	return 0;
+}
+
+int radeon_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
+		     unsigned long arg)
+{
+	drm_file_t	*priv	= filp->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_ctx_t	ctx;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+	DRM_DEBUG("%d\n", ctx.handle);
+	return radeon_context_switch(dev, dev->last_context, ctx.handle);
+}
+
+int radeon_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+	drm_file_t	*priv	= filp->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_ctx_t	ctx;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+	DRM_DEBUG("%d\n", ctx.handle);
+	radeon_context_switch_complete(dev, ctx.handle);
+
+	return 0;
+}
+
+int radeon_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
+		 unsigned long arg)
+{
+	drm_file_t	*priv	= filp->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_ctx_t	ctx;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+	DRM_DEBUG("%d\n", ctx.handle);
+	drm_ctxbitmap_free(dev, ctx.handle);
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/radeon_cp.c linux/drivers/char/drm/radeon_cp.c
--- v2.4.0/linux/drivers/char/drm/radeon_cp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/radeon_cp.c	Fri Jan 19 13:34:08 2001
@@ -0,0 +1,1314 @@
+/* radeon_cp.c -- CP support for Radeon -*- linux-c -*-
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "radeon_drv.h"
+
+#include <linux/interrupt.h>	/* For task queue support */
+#include <linux/delay.h>
+
+#define RADEON_FIFO_DEBUG	0
+
+
+/* CP microcode (from ATI) */
+static u32 radeon_cp_microcode[][2] = {
+	{ 0x21007000, 0000000000 },
+	{ 0x20007000, 0000000000 },
+	{ 0x000000b4, 0x00000004 },
+	{ 0x000000b8, 0x00000004 },
+	{ 0x6f5b4d4c, 0000000000 },
+	{ 0x4c4c427f, 0000000000 },
+	{ 0x5b568a92, 0000000000 },
+	{ 0x4ca09c6d, 0000000000 },
+	{ 0xad4c4c4c, 0000000000 },
+	{ 0x4ce1af3d, 0000000000 },
+	{ 0xd8afafaf, 0000000000 },
+	{ 0xd64c4cdc, 0000000000 },
+	{ 0x4cd10d10, 0000000000 },
+	{ 0x000f0000, 0x00000016 },
+	{ 0x362f242d, 0000000000 },
+	{ 0x00000012, 0x00000004 },
+	{ 0x000f0000, 0x00000016 },
+	{ 0x362f282d, 0000000000 },
+	{ 0x000380e7, 0x00000002 },
+	{ 0x04002c97, 0x00000002 },
+	{ 0x000f0001, 0x00000016 },
+	{ 0x333a3730, 0000000000 },
+	{ 0x000077ef, 0x00000002 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x00000021, 0x0000001a },
+	{ 0x00004000, 0x0000001e },
+	{ 0x00061000, 0x00000002 },
+	{ 0x00000021, 0x0000001a },
+	{ 0x00004000, 0x0000001e },
+	{ 0x00061000, 0x00000002 },
+	{ 0x00000021, 0x0000001a },
+	{ 0x00004000, 0x0000001e },
+	{ 0x00000017, 0x00000004 },
+	{ 0x0003802b, 0x00000002 },
+	{ 0x040067e0, 0x00000002 },
+	{ 0x00000017, 0x00000004 },
+	{ 0x000077e0, 0x00000002 },
+	{ 0x00065000, 0x00000002 },
+	{ 0x000037e1, 0x00000002 },
+	{ 0x040067e1, 0x00000006 },
+	{ 0x000077e0, 0x00000002 },
+	{ 0x000077e1, 0x00000002 },
+	{ 0x000077e1, 0x00000006 },
+	{ 0xffffffff, 0000000000 },
+	{ 0x10000000, 0000000000 },
+	{ 0x0003802b, 0x00000002 },
+	{ 0x040067e0, 0x00000006 },
+	{ 0x00007675, 0x00000002 },
+	{ 0x00007676, 0x00000002 },
+	{ 0x00007677, 0x00000002 },
+	{ 0x00007678, 0x00000006 },
+	{ 0x0003802c, 0x00000002 },
+	{ 0x04002676, 0x00000002 },
+	{ 0x00007677, 0x00000002 },
+	{ 0x00007678, 0x00000006 },
+	{ 0x0000002f, 0x00000018 },
+	{ 0x0000002f, 0x00000018 },
+	{ 0000000000, 0x00000006 },
+	{ 0x00000030, 0x00000018 },
+	{ 0x00000030, 0x00000018 },
+	{ 0000000000, 0x00000006 },
+	{ 0x01605000, 0x00000002 },
+	{ 0x00065000, 0x00000002 },
+	{ 0x00098000, 0x00000002 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x64c0603e, 0x00000004 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x00080000, 0x00000016 },
+	{ 0000000000, 0000000000 },
+	{ 0x0400251d, 0x00000002 },
+	{ 0x00007580, 0x00000002 },
+	{ 0x00067581, 0x00000002 },
+	{ 0x04002580, 0x00000002 },
+	{ 0x00067581, 0x00000002 },
+	{ 0x00000049, 0x00000004 },
+	{ 0x00005000, 0000000000 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x0000750e, 0x00000002 },
+	{ 0x00019000, 0x00000002 },
+	{ 0x00011055, 0x00000014 },
+	{ 0x00000055, 0x00000012 },
+	{ 0x0400250f, 0x00000002 },
+	{ 0x0000504f, 0x00000004 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x00007565, 0x00000002 },
+	{ 0x00007566, 0x00000002 },
+	{ 0x00000058, 0x00000004 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x01e655b4, 0x00000002 },
+	{ 0x4401b0e4, 0x00000002 },
+	{ 0x01c110e4, 0x00000002 },
+	{ 0x26667066, 0x00000018 },
+	{ 0x040c2565, 0x00000002 },
+	{ 0x00000066, 0x00000018 },
+	{ 0x04002564, 0x00000002 },
+	{ 0x00007566, 0x00000002 },
+	{ 0x0000005d, 0x00000004 },
+	{ 0x00401069, 0x00000008 },
+	{ 0x00101000, 0x00000002 },
+	{ 0x000d80ff, 0x00000002 },
+	{ 0x0080006c, 0x00000008 },
+	{ 0x000f9000, 0x00000002 },
+	{ 0x000e00ff, 0x00000002 },
+	{ 0000000000, 0x00000006 },
+	{ 0x0000008f, 0x00000018 },
+	{ 0x0000005b, 0x00000004 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x00007576, 0x00000002 },
+	{ 0x00065000, 0x00000002 },
+	{ 0x00009000, 0x00000002 },
+	{ 0x00041000, 0x00000002 },
+	{ 0x0c00350e, 0x00000002 },
+	{ 0x00049000, 0x00000002 },
+	{ 0x00051000, 0x00000002 },
+	{ 0x01e785f8, 0x00000002 },
+	{ 0x00200000, 0x00000002 },
+	{ 0x0060007e, 0x0000000c },
+	{ 0x00007563, 0x00000002 },
+	{ 0x006075f0, 0x00000021 },
+	{ 0x20007073, 0x00000004 },
+	{ 0x00005073, 0x00000004 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x00007576, 0x00000002 },
+	{ 0x00007577, 0x00000002 },
+	{ 0x0000750e, 0x00000002 },
+	{ 0x0000750f, 0x00000002 },
+	{ 0x00a05000, 0x00000002 },
+	{ 0x00600083, 0x0000000c },
+	{ 0x006075f0, 0x00000021 },
+	{ 0x000075f8, 0x00000002 },
+	{ 0x00000083, 0x00000004 },
+	{ 0x000a750e, 0x00000002 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x0020750f, 0x00000002 },
+	{ 0x00600086, 0x00000004 },
+	{ 0x00007570, 0x00000002 },
+	{ 0x00007571, 0x00000002 },
+	{ 0x00007572, 0x00000006 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x00005000, 0x00000002 },
+	{ 0x00a05000, 0x00000002 },
+	{ 0x00007568, 0x00000002 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x00000095, 0x0000000c },
+	{ 0x00058000, 0x00000002 },
+	{ 0x0c607562, 0x00000002 },
+	{ 0x00000097, 0x00000004 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x00600096, 0x00000004 },
+	{ 0x400070e5, 0000000000 },
+	{ 0x000380e6, 0x00000002 },
+	{ 0x040025c5, 0x00000002 },
+	{ 0x000380e5, 0x00000002 },
+	{ 0x000000a8, 0x0000001c },
+	{ 0x000650aa, 0x00000018 },
+	{ 0x040025bb, 0x00000002 },
+	{ 0x000610ab, 0x00000018 },
+	{ 0x040075bc, 0000000000 },
+	{ 0x000075bb, 0x00000002 },
+	{ 0x000075bc, 0000000000 },
+	{ 0x00090000, 0x00000006 },
+	{ 0x00090000, 0x00000002 },
+	{ 0x000d8002, 0x00000006 },
+	{ 0x00007832, 0x00000002 },
+	{ 0x00005000, 0x00000002 },
+	{ 0x000380e7, 0x00000002 },
+	{ 0x04002c97, 0x00000002 },
+	{ 0x00007820, 0x00000002 },
+	{ 0x00007821, 0x00000002 },
+	{ 0x00007800, 0000000000 },
+	{ 0x01200000, 0x00000002 },
+	{ 0x20077000, 0x00000002 },
+	{ 0x01200000, 0x00000002 },
+	{ 0x20007000, 0x00000002 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x0120751b, 0x00000002 },
+	{ 0x8040750a, 0x00000002 },
+	{ 0x8040750b, 0x00000002 },
+	{ 0x00110000, 0x00000002 },
+	{ 0x000380e5, 0x00000002 },
+	{ 0x000000c6, 0x0000001c },
+	{ 0x000610ab, 0x00000018 },
+	{ 0x844075bd, 0x00000002 },
+	{ 0x000610aa, 0x00000018 },
+	{ 0x840075bb, 0x00000002 },
+	{ 0x000610ab, 0x00000018 },
+	{ 0x844075bc, 0x00000002 },
+	{ 0x000000c9, 0x00000004 },
+	{ 0x804075bd, 0x00000002 },
+	{ 0x800075bb, 0x00000002 },
+	{ 0x804075bc, 0x00000002 },
+	{ 0x00108000, 0x00000002 },
+	{ 0x01400000, 0x00000002 },
+	{ 0x006000cd, 0x0000000c },
+	{ 0x20c07000, 0x00000020 },
+	{ 0x000000cf, 0x00000012 },
+	{ 0x00800000, 0x00000006 },
+	{ 0x0080751d, 0x00000006 },
+	{ 0000000000, 0000000000 },
+	{ 0x0000775c, 0x00000002 },
+	{ 0x00a05000, 0x00000002 },
+	{ 0x00661000, 0x00000002 },
+	{ 0x0460275d, 0x00000020 },
+	{ 0x00004000, 0000000000 },
+	{ 0x01e00830, 0x00000002 },
+	{ 0x21007000, 0000000000 },
+	{ 0x6464614d, 0000000000 },
+	{ 0x69687420, 0000000000 },
+	{ 0x00000073, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0x00005000, 0x00000002 },
+	{ 0x000380d0, 0x00000002 },
+	{ 0x040025e0, 0x00000002 },
+	{ 0x000075e1, 0000000000 },
+	{ 0x00000001, 0000000000 },
+	{ 0x000380e0, 0x00000002 },
+	{ 0x04002394, 0x00000002 },
+	{ 0x00005000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0x00000008, 0000000000 },
+	{ 0x00000004, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+};
+
+
+#define DO_IOREMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
+
+#define DO_IOREMAPFREE(_m)						\
+	do {								\
+		if ((_m)->handle && (_m)->size)				\
+			drm_ioremapfree((_m)->handle, (_m)->size);	\
+	} while (0)
+
+#define DO_FIND_MAP(_m, _o)						\
+	do {								\
+		int _i;							\
+		for (_i = 0; _i < dev->map_count; _i++) {		\
+			if (dev->maplist[_i]->offset == _o) {		\
+				_m = dev->maplist[_i];			\
+				break;					\
+			}						\
+		}							\
+	} while (0)
+
+
+int RADEON_READ_PLL(drm_device_t *dev, int addr)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
+	return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+}
+
+#if RADEON_FIFO_DEBUG
+static void radeon_status( drm_radeon_private_t *dev_priv )
+{
+	printk( "%s:\n", __FUNCTION__ );
+	printk( "RBBM_STATUS = 0x%08x\n",
+		(unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) );
+	printk( "CP_RB_RTPR = 0x%08x\n",
+		(unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
+	printk( "CP_RB_WTPR = 0x%08x\n",
+		(unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
+}
+#endif
+
+
+/* ================================================================
+ * Engine, FIFO control
+ */
+
+static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
+{
+	u32 tmp;
+	int i;
+
+	tmp  = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
+	tmp |= RADEON_RB2D_DC_FLUSH_ALL;
+	RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
+
+	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+		if ( !(RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT )
+		       & RADEON_RB2D_DC_BUSY) ) {
+			return 0;
+		}
+		udelay( 1 );
+	}
+
+#if RADEON_FIFO_DEBUG
+	DRM_ERROR( "failed!\n" );
+	radeon_status( dev_priv );
+#endif
+	return -EBUSY;
+}
+
+static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
+				    int entries )
+{
+	int i;
+
+	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+		int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
+			      & RADEON_RBBM_FIFOCNT_MASK );
+		if ( slots >= entries ) return 0;
+		udelay( 1 );
+	}
+
+#if RADEON_FIFO_DEBUG
+	DRM_ERROR( "failed!\n" );
+	radeon_status( dev_priv );
+#endif
+	return -EBUSY;
+}
+
+static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
+{
+	int i, ret;
+
+	ret = radeon_do_wait_for_fifo( dev_priv, 64 );
+	if ( ret < 0 ) return ret;
+
+	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+		if ( !(RADEON_READ( RADEON_RBBM_STATUS )
+		       & RADEON_RBBM_ACTIVE) ) {
+			radeon_do_pixcache_flush( dev_priv );
+			return 0;
+		}
+		udelay( 1 );
+	}
+
+#if RADEON_FIFO_DEBUG
+	DRM_ERROR( "failed!\n" );
+	radeon_status( dev_priv );
+#endif
+	return -EBUSY;
+}
+
+
+/* ================================================================
+ * CP control, initialization
+ */
+
+/* Load the microcode for the CP */
+static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
+{
+	int i;
+
+	radeon_do_wait_for_idle( dev_priv );
+
+	RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 );
+	for ( i = 0 ; i < 256 ; i++ ) {
+		RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
+			      radeon_cp_microcode[i][1] );
+		RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
+			      radeon_cp_microcode[i][0] );
+	}
+}
+
+/* Flush any pending commands to the CP.  This should only be used just
+ * prior to a wait for idle, as it informs the engine that the command
+ * stream is ending.
+ */
+static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
+{
+#if 0
+	u32 tmp;
+
+	tmp = RADEON_READ( RADEON_CP_RB_WPTR ) | (1 << 31);
+	RADEON_WRITE( RADEON_CP_RB_WPTR, tmp );
+#endif
+}
+
+/* Wait for the CP to go idle.
+ */
+int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
+{
+	RING_LOCALS;
+
+	BEGIN_RING( 6 );
+
+	RADEON_PURGE_CACHE();
+	RADEON_PURGE_ZCACHE();
+	RADEON_WAIT_UNTIL_IDLE();
+
+	ADVANCE_RING();
+
+	return radeon_do_wait_for_idle( dev_priv );
+}
+
+/* Start the Command Processor.
+ */
+static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
+{
+	RING_LOCALS;
+
+	radeon_do_wait_for_idle( dev_priv );
+
+	RADEON_WRITE( RADEON_CP_CSQ_CNTL, dev_priv->cp_mode );
+
+	dev_priv->cp_running = 1;
+
+	BEGIN_RING( 6 );
+
+	RADEON_PURGE_CACHE();
+	RADEON_PURGE_ZCACHE();
+	RADEON_WAIT_UNTIL_IDLE();
+
+	ADVANCE_RING();
+}
+
+/* Reset the Command Processor.  This will not flush any pending
+ * commands, so you must wait for the CP command stream to complete
+ * before calling this routine.
+ */
+static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
+{
+	u32 cur_read_ptr;
+
+	cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
+	RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
+	*dev_priv->ring.head = cur_read_ptr;
+	dev_priv->ring.tail = cur_read_ptr;
+}
+
+/* Stop the Command Processor.  This will not flush any pending
+ * commands, so you must flush the command stream and wait for the CP
+ * to go idle before calling this routine.
+ */
+static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
+{
+	RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
+
+	dev_priv->cp_running = 0;
+}
+
+/* Reset the engine.  This will stop the CP if it is running.
+ */
+static int radeon_do_engine_reset( drm_device_t *dev )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	radeon_do_pixcache_flush( dev_priv );
+
+	clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX );
+	mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL );
+
+	/* FIXME: remove magic number here and in radeon ddx driver!!! */
+	RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl | 0x003f00000 );
+
+	rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET );
+
+	RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset |
+						RADEON_SOFT_RESET_CP |
+						RADEON_SOFT_RESET_HI |
+						RADEON_SOFT_RESET_SE |
+						RADEON_SOFT_RESET_RE |
+						RADEON_SOFT_RESET_PP |
+						RADEON_SOFT_RESET_E2 |
+						RADEON_SOFT_RESET_RB |
+						RADEON_SOFT_RESET_HDP ) );
+	RADEON_READ( RADEON_RBBM_SOFT_RESET );
+	RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset &
+						~( RADEON_SOFT_RESET_CP |
+						   RADEON_SOFT_RESET_HI |
+						   RADEON_SOFT_RESET_SE |
+						   RADEON_SOFT_RESET_RE |
+						   RADEON_SOFT_RESET_PP |
+						   RADEON_SOFT_RESET_E2 |
+						   RADEON_SOFT_RESET_RB |
+						   RADEON_SOFT_RESET_HDP ) ) );
+	RADEON_READ( RADEON_RBBM_SOFT_RESET );
+
+
+	RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl );
+	RADEON_WRITE( RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
+	RADEON_WRITE( RADEON_RBBM_SOFT_RESET,  rbbm_soft_reset );
+
+	/* Reset the CP ring */
+	radeon_do_cp_reset( dev_priv );
+
+	/* The CP is no longer running after an engine reset */
+	dev_priv->cp_running = 0;
+
+	/* Reset any pending vertex, indirect buffers */
+	radeon_freelist_reset( dev );
+
+	return 0;
+}
+
+static void radeon_cp_init_ring_buffer( drm_device_t *dev )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	u32 ring_start, cur_read_ptr;
+	u32 tmp;
+
+	/* Initialize the memory controller */
+	RADEON_WRITE( RADEON_MC_FB_LOCATION,
+		      (dev_priv->agp_vm_start - 1) & 0xffff0000 );
+	RADEON_WRITE( RADEON_MC_AGP_LOCATION,
+		      (((dev_priv->agp_vm_start - 1 +
+			 dev_priv->agp_size) & 0xffff0000) |
+		       (dev_priv->agp_vm_start >> 16)) );
+
+	ring_start = (dev_priv->cp_ring->offset
+		      - dev->agp->base
+		      + dev_priv->agp_vm_start);
+
+	RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
+
+	/* Set the write pointer delay */
+	RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
+
+	/* Initialize the ring buffer's read and write pointers */
+	cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
+	RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
+	*dev_priv->ring.head = cur_read_ptr;
+	dev_priv->ring.tail = cur_read_ptr;
+
+	RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset );
+
+	/* Set ring buffer size */
+	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
+
+	radeon_do_wait_for_idle( dev_priv );
+
+	/* Turn off PCI GART */
+	tmp = RADEON_READ( RADEON_AIC_CNTL ) & ~RADEON_PCIGART_TRANSLATE_EN;
+	RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+
+	/* Turn on bus mastering */
+	tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
+	RADEON_WRITE( RADEON_BUS_CNTL, tmp );
+
+	/* Sync everything up */
+	RADEON_WRITE( RADEON_ISYNC_CNTL,
+		      (RADEON_ISYNC_ANY2D_IDLE3D |
+		       RADEON_ISYNC_ANY3D_IDLE2D |
+		       RADEON_ISYNC_WAIT_IDLEGUI |
+		       RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
+}
+
+static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
+{
+	drm_radeon_private_t *dev_priv;
+        int i;
+
+	dev_priv = drm_alloc( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
+	if ( dev_priv == NULL )
+		return -ENOMEM;
+	dev->dev_private = (void *)dev_priv;
+
+	memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
+
+	dev_priv->is_pci = init->is_pci;
+
+	/* We don't support PCI cards until PCI GART is implemented.
+	 * Fail here so we can remove all checks for PCI cards around
+	 * the CP ring code.
+	 */
+	if ( dev_priv->is_pci ) {
+		drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+		dev->dev_private = NULL;
+		return -EINVAL;
+	}
+
+	dev_priv->usec_timeout = init->usec_timeout;
+	if ( dev_priv->usec_timeout < 1 ||
+	     dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
+		drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+		dev->dev_private = NULL;
+		return -EINVAL;
+	}
+
+	dev_priv->cp_mode = init->cp_mode;
+
+	/* Simple idle check.
+	 */
+	atomic_set( &dev_priv->idle_count, 0 );
+
+	/* We don't support anything other than bus-mastering ring mode,
+	 * but the ring can be in either AGP or PCI space for the ring
+	 * read pointer.
+	 */
+	if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
+	     ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
+		drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+		dev->dev_private = NULL;
+		return -EINVAL;
+	}
+
+	switch ( init->fb_bpp ) {
+	case 16:
+		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
+		break;
+	case 32:
+	default:
+		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
+		break;
+	}
+	dev_priv->front_offset	= init->front_offset;
+	dev_priv->front_pitch	= init->front_pitch;
+	dev_priv->back_offset	= init->back_offset;
+	dev_priv->back_pitch	= init->back_pitch;
+
+	switch ( init->depth_bpp ) {
+	case 16:
+		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+		break;
+	case 32:
+	default:
+		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+		break;
+	}
+	dev_priv->depth_offset	= init->depth_offset;
+	dev_priv->depth_pitch	= init->depth_pitch;
+
+	dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
+					(dev_priv->front_offset >> 10));
+	dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
+				       (dev_priv->back_offset >> 10));
+	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
+					(dev_priv->depth_offset >> 10));
+
+	/* Hardware state for depth clears.  Remove this if/when we no
+	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
+	 * all values to prevent unwanted 3D state from slipping through
+	 * and screwing with the clear operation.
+	 */
+	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
+					   RADEON_Z_ENABLE |
+					   (dev_priv->color_fmt << 10) |
+					   RADEON_ZBLOCK16);
+
+	dev_priv->depth_clear.rb3d_zstencilcntl = (dev_priv->depth_fmt |
+						   RADEON_Z_TEST_ALWAYS |
+						   RADEON_STENCIL_TEST_ALWAYS |
+						   RADEON_STENCIL_S_FAIL_KEEP |
+						   RADEON_STENCIL_ZPASS_KEEP |
+						   RADEON_STENCIL_ZFAIL_KEEP |
+						   RADEON_Z_WRITE_ENABLE);
+
+	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
+					 RADEON_BFACE_SOLID |
+					 RADEON_FFACE_SOLID |
+					 RADEON_FLAT_SHADE_VTX_LAST |
+
+					 RADEON_DIFFUSE_SHADE_FLAT |
+					 RADEON_ALPHA_SHADE_FLAT |
+					 RADEON_SPECULAR_SHADE_FLAT |
+					 RADEON_FOG_SHADE_FLAT |
+
+					 RADEON_VTX_PIX_CENTER_OGL |
+					 RADEON_ROUND_MODE_TRUNC |
+					 RADEON_ROUND_PREC_8TH_PIX);
+
+	/* FIXME: We want multiple shared areas, including one shared
+	 * only by the X Server and kernel module.
+	 */
+	for ( i = 0 ; i < dev->map_count ; i++ ) {
+		if ( dev->maplist[i]->type == _DRM_SHM ) {
+			dev_priv->sarea = dev->maplist[i];
+			break;
+		}
+	}
+
+	DO_FIND_MAP( dev_priv->fb, init->fb_offset );
+	DO_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+	DO_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
+	DO_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+	DO_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+
+	if ( !dev_priv->is_pci ) {
+		DO_FIND_MAP( dev_priv->agp_textures,
+			     init->agp_textures_offset );
+	}
+
+	dev_priv->sarea_priv =
+		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
+				       init->sarea_priv_offset);
+
+	DO_IOREMAP( dev_priv->cp_ring );
+	DO_IOREMAP( dev_priv->ring_rptr );
+	DO_IOREMAP( dev_priv->buffers );
+#if 0
+	if ( !dev_priv->is_pci ) {
+		DO_IOREMAP( dev_priv->agp_textures );
+	}
+#endif
+
+	dev_priv->agp_size = init->agp_size;
+	dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
+	dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
+					- dev->agp->base
+					+ dev_priv->agp_vm_start);
+
+	dev_priv->ring.head = ((__volatile__ u32 *)
+			       dev_priv->ring_rptr->handle);
+
+	dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;
+	dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
+			      + init->ring_size / sizeof(u32));
+	dev_priv->ring.size = init->ring_size;
+	dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
+
+	dev_priv->ring.tail_mask =
+		(dev_priv->ring.size / sizeof(u32)) - 1;
+
+#if 0
+	/* Initialize the scratch register pointer.  This will cause
+	 * the scratch register values to be written out to memory
+	 * whenever they are updated.
+	 * FIXME: This doesn't quite work yet, so we're disabling it
+	 * for the release.
+	 */
+	RADEON_WRITE( RADEON_SCRATCH_ADDR, (dev_priv->ring_rptr->offset +
+					    RADEON_SCRATCH_REG_OFFSET) );
+	RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
+#endif
+
+	dev_priv->scratch = ((__volatile__ u32 *)
+			     dev_priv->ring_rptr->handle +
+			     (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+
+	dev_priv->sarea_priv->last_frame = 0;
+	RADEON_WRITE( RADEON_LAST_FRAME_REG,
+		      dev_priv->sarea_priv->last_frame );
+
+	dev_priv->sarea_priv->last_dispatch = 0;
+	RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
+		      dev_priv->sarea_priv->last_dispatch );
+
+	dev_priv->sarea_priv->last_clear = 0;
+	RADEON_WRITE( RADEON_LAST_CLEAR_REG,
+		      dev_priv->sarea_priv->last_clear );
+
+	radeon_cp_load_microcode( dev_priv );
+	radeon_cp_init_ring_buffer( dev );
+	radeon_do_engine_reset( dev );
+
+#if ROTATE_BUFS
+	dev_priv->last_buf = 0;
+#endif
+
+	return 0;
+}
+
+static int radeon_do_cleanup_cp( drm_device_t *dev )
+{
+	if ( dev->dev_private ) {
+		drm_radeon_private_t *dev_priv = dev->dev_private;
+
+		DO_IOREMAPFREE( dev_priv->cp_ring );
+		DO_IOREMAPFREE( dev_priv->ring_rptr );
+		DO_IOREMAPFREE( dev_priv->buffers );
+#if 0
+		if ( !dev_priv->is_pci ) {
+			DO_IOREMAPFREE( dev_priv->agp_textures );
+		}
+#endif
+
+		drm_free( dev->dev_private, sizeof(drm_radeon_private_t),
+			  DRM_MEM_DRIVER );
+		dev->dev_private = NULL;
+	}
+
+	return 0;
+}
+
+int radeon_cp_init( struct inode *inode, struct file *filp,
+		    unsigned int cmd, unsigned long arg )
+{
+        drm_file_t *priv = filp->private_data;
+        drm_device_t *dev = priv->dev;
+	drm_radeon_init_t init;
+
+	if ( copy_from_user( &init, (drm_radeon_init_t *)arg, sizeof(init) ) )
+		return -EFAULT;
+
+	switch ( init.func ) {
+	case RADEON_INIT_CP:
+		return radeon_do_init_cp( dev, &init );
+	case RADEON_CLEANUP_CP:
+		return radeon_do_cleanup_cp( dev );
+	}
+
+	return -EINVAL;
+}
+
+int radeon_cp_start( struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg )
+{
+        drm_file_t *priv = filp->private_data;
+        drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+	if ( dev_priv->cp_running ) {
+		DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
+		return 0;
+	}
+	if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) {
+		DRM_DEBUG( "%s called with bogus CP mode (%d)\n",
+			   __FUNCTION__, dev_priv->cp_mode );
+		return 0;
+	}
+
+	radeon_do_cp_start( dev_priv );
+
+	return 0;
+}
+
+/* Stop the CP.  The engine must have been idled before calling this
+ * routine.
+ */
+int radeon_cp_stop( struct inode *inode, struct file *filp,
+		    unsigned int cmd, unsigned long arg )
+{
+        drm_file_t *priv = filp->private_data;
+        drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_cp_stop_t stop;
+	int ret;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) )
+		return -EFAULT;
+
+	/* Flush any pending CP commands.  This ensures any outstanding
+	 * commands are exectuted by the engine before we turn it off.
+	 */
+	if ( stop.flush ) {
+		radeon_do_cp_flush( dev_priv );
+	}
+
+	/* If we fail to make the engine go idle, we return an error
+	 * code so that the DRM ioctl wrapper can try again.
+	 */
+	if ( stop.idle ) {
+		ret = radeon_do_cp_idle( dev_priv );
+		if ( ret < 0 ) return ret;
+	}
+
+	/* Finally, we can turn off the CP.  If the engine isn't idle,
+	 * we will get some dropped triangles as they won't be fully
+	 * rendered before the CP is shut down.
+	 */
+	radeon_do_cp_stop( dev_priv );
+
+	/* Reset the engine */
+	radeon_do_engine_reset( dev );
+
+	return 0;
+}
+
+/* Just reset the CP ring.  Called as part of an X Server engine reset.
+ */
+int radeon_cp_reset( struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg )
+{
+        drm_file_t *priv = filp->private_data;
+        drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+	if ( !dev_priv ) {
+		DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	radeon_do_cp_reset( dev_priv );
+
+	/* The CP is no longer running after an engine reset */
+	dev_priv->cp_running = 0;
+
+	return 0;
+}
+
+int radeon_cp_idle( struct inode *inode, struct file *filp,
+		    unsigned int cmd, unsigned long arg )
+{
+        drm_file_t *priv = filp->private_data;
+        drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	return radeon_do_cp_idle( dev_priv );
+}
+
+int radeon_engine_reset( struct inode *inode, struct file *filp,
+			 unsigned int cmd, unsigned long arg )
+{
+        drm_file_t *priv = filp->private_data;
+        drm_device_t *dev = priv->dev;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	return radeon_do_engine_reset( dev );
+}
+
+
+/* ================================================================
+ * Fullscreen mode
+ */
+
+static int radeon_do_init_pageflip( drm_device_t *dev )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	dev_priv->crtc_offset =      RADEON_READ( RADEON_CRTC_OFFSET );
+	dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL );
+
+	RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset );
+	RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL,
+		      dev_priv->crtc_offset_cntl |
+		      RADEON_CRTC_OFFSET_FLIP_CNTL );
+
+	dev_priv->page_flipping = 1;
+	dev_priv->current_page = 0;
+
+	return 0;
+}
+
+int radeon_do_cleanup_pageflip( drm_device_t *dev )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	RADEON_WRITE( RADEON_CRTC_OFFSET,      dev_priv->crtc_offset );
+	RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
+
+	dev_priv->page_flipping = 0;
+	dev_priv->current_page = 0;
+
+	return 0;
+}
+
+int radeon_fullscreen( struct inode *inode, struct file *filp,
+		       unsigned int cmd, unsigned long arg )
+{
+        drm_file_t *priv = filp->private_data;
+        drm_device_t *dev = priv->dev;
+	drm_radeon_fullscreen_t fs;
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg,
+			     sizeof(fs) ) )
+		return -EFAULT;
+
+	switch ( fs.func ) {
+	case RADEON_INIT_FULLSCREEN:
+		return radeon_do_init_pageflip( dev );
+	case RADEON_CLEANUP_FULLSCREEN:
+		return radeon_do_cleanup_pageflip( dev );
+	}
+
+	return -EINVAL;
+}
+
+
+/* ================================================================
+ * Freelist management
+ */
+#define RADEON_BUFFER_USED	0xffffffff
+#define RADEON_BUFFER_FREE	0
+
+#if 0
+static int radeon_freelist_init( drm_device_t *dev )
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_buf_t *buf;
+	drm_radeon_buf_priv_t *buf_priv;
+	drm_radeon_freelist_t *entry;
+	int i;
+
+	dev_priv->head = drm_alloc( sizeof(drm_radeon_freelist_t),
+				    DRM_MEM_DRIVER );
+	if ( dev_priv->head == NULL )
+		return -ENOMEM;
+
+	memset( dev_priv->head, 0, sizeof(drm_radeon_freelist_t) );
+	dev_priv->head->age = RADEON_BUFFER_USED;
+
+	for ( i = 0 ; i < dma->buf_count ; i++ ) {
+		buf = dma->buflist[i];
+		buf_priv = buf->dev_private;
+
+		entry = drm_alloc( sizeof(drm_radeon_freelist_t),
+				   DRM_MEM_DRIVER );
+		if ( !entry ) return -ENOMEM;
+
+		entry->age = RADEON_BUFFER_FREE;
+		entry->buf = buf;
+		entry->prev = dev_priv->head;
+		entry->next = dev_priv->head->next;
+		if ( !entry->next )
+			dev_priv->tail = entry;
+
+		buf_priv->discard = 0;
+		buf_priv->dispatched = 0;
+		buf_priv->list_entry = entry;
+
+		dev_priv->head->next = entry;
+
+		if ( dev_priv->head->next )
+			dev_priv->head->next->prev = entry;
+	}
+
+	return 0;
+
+}
+#endif
+
+drm_buf_t *radeon_freelist_get( drm_device_t *dev )
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_buf_priv_t *buf_priv;
+	drm_buf_t *buf;
+	int i, t;
+#if ROTATE_BUFS
+	int start;
+#endif
+
+	/* FIXME: Optimize -- use freelist code */
+
+	for ( i = 0 ; i < dma->buf_count ; i++ ) {
+		buf = dma->buflist[i];
+		buf_priv = buf->dev_private;
+		if ( buf->pid == 0 ) {
+			DRM_DEBUG( "  ret buf=%d last=%d pid=0\n",
+				   buf->idx, dev_priv->last_buf );
+			return buf;
+		}
+		DRM_DEBUG( "    skipping buf=%d pid=%d\n",
+			   buf->idx, buf->pid );
+	}
+
+#if ROTATE_BUFS
+	if ( ++dev_priv->last_buf >= dma->buf_count )
+		dev_priv->last_buf = 0;
+	start = dev_priv->last_buf;
+#endif
+	for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
+#if 0
+		/* FIXME: Disable this for now */
+		u32 done_age = dev_priv->scratch[RADEON_LAST_DISPATCH];
+#else
+		u32 done_age = RADEON_READ( RADEON_LAST_DISPATCH_REG );
+#endif
+#if ROTATE_BUFS
+		for ( i = start ; i < dma->buf_count ; i++ ) {
+#else
+		for ( i = 0 ; i < dma->buf_count ; i++ ) {
+#endif
+			buf = dma->buflist[i];
+			buf_priv = buf->dev_private;
+			if ( buf->pending && buf_priv->age <= done_age ) {
+				/* The buffer has been processed, so it
+				 * can now be used.
+				 */
+				buf->pending = 0;
+				DRM_DEBUG( "  ret buf=%d last=%d age=%d done=%d\n", buf->idx, dev_priv->last_buf, buf_priv->age, done_age );
+				return buf;
+			}
+			DRM_DEBUG( "    skipping buf=%d age=%d done=%d\n",
+				   buf->idx, buf_priv->age,
+				   done_age );
+#if ROTATE_BUFS
+			start = 0;
+#endif
+		}
+		udelay( 1 );
+	}
+
+	DRM_ERROR( "returning NULL!\n" );
+	return NULL;
+}
+
+void radeon_freelist_reset( drm_device_t *dev )
+{
+	drm_device_dma_t *dma = dev->dma;
+#if ROTATE_BUFS
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+#endif
+	int i;
+
+#if ROTATE_BUFS
+	dev_priv->last_buf = 0;
+#endif
+	for ( i = 0 ; i < dma->buf_count ; i++ ) {
+		drm_buf_t *buf = dma->buflist[i];
+		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+		buf_priv->age = 0;
+	}
+}
+
+
+/* ================================================================
+ * CP command submission
+ */
+
+int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
+{
+	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
+	int i;
+
+	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+		ring->space = *ring->head - ring->tail;
+		if ( ring->space <= 0 )
+			ring->space += ring->size;
+
+		if ( ring->space >= n )
+			return 0;
+
+		udelay( 1 );
+	}
+
+	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
+	DRM_ERROR( "failed!\n" );
+	return -EBUSY;
+}
+
+void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
+
+	ring->space = *ring->head - ring->tail;
+	if ( ring->space == 0 )
+		atomic_inc( &dev_priv->idle_count );
+	if ( ring->space <= 0 )
+		ring->space += ring->size;
+}
+
+static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
+{
+	int i;
+	drm_buf_t *buf;
+
+	for ( i = d->granted_count ; i < d->request_count ; i++ ) {
+		buf = radeon_freelist_get( dev );
+		if ( !buf ) return -EAGAIN;
+
+		buf->pid = current->pid;
+
+		if ( copy_to_user( &d->request_indices[i], &buf->idx,
+				   sizeof(buf->idx) ) )
+			return -EFAULT;
+		if ( copy_to_user( &d->request_sizes[i], &buf->total,
+				   sizeof(buf->total) ) )
+			return -EFAULT;
+
+		d->granted_count++;
+	}
+	return 0;
+}
+
+int radeon_cp_buffers( struct inode *inode, struct file *filp,
+		       unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_device_dma_t *dma = dev->dma;
+	int ret = 0;
+	drm_dma_t d;
+
+	if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) )
+		return -EFAULT;
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	/* Please don't send us buffers.
+	 */
+	if ( d.send_count != 0 ) {
+		DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
+			   current->pid, d.send_count );
+		return -EINVAL;
+	}
+
+	/* We'll send you buffers.
+	 */
+	if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
+		DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
+			   current->pid, d.request_count, dma->buf_count );
+		return -EINVAL;
+	}
+
+	d.granted_count = 0;
+
+	if ( d.request_count ) {
+		ret = radeon_cp_get_buffers( dev, &d );
+	}
+
+	if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) )
+		return -EFAULT;
+
+	return ret;
+}
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/radeon_drm.h linux/drivers/char/drm/radeon_drm.h
--- v2.4.0/linux/drivers/char/drm/radeon_drm.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/radeon_drm.h	Fri Jan 19 13:34:08 2001
@@ -0,0 +1,325 @@
+/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*-
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __RADEON_DRM_H__
+#define __RADEON_DRM_H__
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the X server file (radeon_sarea.h)
+ */
+#ifndef __RADEON_SAREA_DEFINES__
+#define __RADEON_SAREA_DEFINES__
+
+/* What needs to be changed for the current vertex buffer?
+ */
+#define RADEON_UPLOAD_CONTEXT		0x00000001
+#define RADEON_UPLOAD_VERTFMT		0x00000002
+#define RADEON_UPLOAD_LINE		0x00000004
+#define RADEON_UPLOAD_BUMPMAP		0x00000008
+#define RADEON_UPLOAD_MASKS		0x00000010
+#define RADEON_UPLOAD_VIEWPORT		0x00000020
+#define RADEON_UPLOAD_SETUP		0x00000040
+#define RADEON_UPLOAD_TCL		0x00000080
+#define RADEON_UPLOAD_MISC		0x00000100
+#define RADEON_UPLOAD_TEX0		0x00000200
+#define RADEON_UPLOAD_TEX1		0x00000400
+#define RADEON_UPLOAD_TEX2		0x00000800
+#define RADEON_UPLOAD_TEX0IMAGES	0x00001000
+#define RADEON_UPLOAD_TEX1IMAGES	0x00002000
+#define RADEON_UPLOAD_TEX2IMAGES	0x00004000
+#define RADEON_UPLOAD_CLIPRECTS		0x00008000 /* handled client-side */
+#define RADEON_REQUIRE_QUIESCENCE	0x00010000
+#define RADEON_UPLOAD_ALL		0x0001ffff
+
+#define RADEON_FRONT			0x1
+#define RADEON_BACK			0x2
+#define RADEON_DEPTH			0x4
+
+/* Primitive types
+ */
+#define RADEON_POINTS			0x1
+#define RADEON_LINES			0x2
+#define RADEON_LINE_STRIP		0x3
+#define RADEON_TRIANGLES		0x4
+#define RADEON_TRIANGLE_FAN		0x5
+#define RADEON_TRIANGLE_STRIP		0x6
+
+/* Vertex/indirect buffer size
+ */
+#define RADEON_BUFFER_SIZE		16384
+
+/* Byte offsets for indirect buffer data
+ */
+#define RADEON_INDEX_PRIM_OFFSET	20
+#define RADEON_HOSTDATA_BLIT_OFFSET	32
+
+#define RADEON_SCRATCH_REG_OFFSET	32
+
+/* Keep these small for testing
+ */
+#define RADEON_NR_SAREA_CLIPRECTS	12
+
+/* There are 2 heaps (local/AGP).  Each region within a heap is a
+ * minimum of 64k, and there are at most 64 of them per heap.
+ */
+#define RADEON_LOCAL_TEX_HEAP		0
+#define RADEON_AGP_TEX_HEAP		1
+#define RADEON_NR_TEX_HEAPS		2
+#define RADEON_NR_TEX_REGIONS		64
+#define RADEON_LOG_TEX_GRANULARITY	16
+
+#define RADEON_MAX_TEXTURE_LEVELS	11
+#define RADEON_MAX_TEXTURE_UNITS	3
+
+#endif /* __RADEON_SAREA_DEFINES__ */
+
+typedef struct {
+	unsigned int red;
+	unsigned int green;
+	unsigned int blue;
+	unsigned int alpha;
+} radeon_color_regs_t;
+
+typedef struct {
+	/* Context state */
+	unsigned int pp_misc;				/* 0x1c14 */
+	unsigned int pp_fog_color;
+	unsigned int re_solid_color;
+	unsigned int rb3d_blendcntl;
+	unsigned int rb3d_depthoffset;
+	unsigned int rb3d_depthpitch;
+	unsigned int rb3d_zstencilcntl;
+
+	unsigned int pp_cntl;				/* 0x1c38 */
+	unsigned int rb3d_cntl;
+	unsigned int rb3d_coloroffset;
+	unsigned int re_width_height;
+	unsigned int rb3d_colorpitch;
+	unsigned int se_cntl;
+
+	/* Vertex format state */
+	unsigned int se_coord_fmt;			/* 0x1c50 */
+
+	/* Line state */
+	unsigned int re_line_pattern;			/* 0x1cd0 */
+	unsigned int re_line_state;
+
+	unsigned int se_line_width;			/* 0x1db8 */
+
+	/* Bumpmap state */
+	unsigned int pp_lum_matrix;			/* 0x1d00 */
+
+	unsigned int pp_rot_matrix_0;			/* 0x1d58 */
+	unsigned int pp_rot_matrix_1;
+
+	/* Mask state */
+	unsigned int rb3d_stencilrefmask;		/* 0x1d7c */
+	unsigned int rb3d_ropcntl;
+	unsigned int rb3d_planemask;
+
+	/* Viewport state */
+	unsigned int se_vport_xscale;			/* 0x1d98 */
+	unsigned int se_vport_xoffset;
+	unsigned int se_vport_yscale;
+	unsigned int se_vport_yoffset;
+	unsigned int se_vport_zscale;
+	unsigned int se_vport_zoffset;
+
+	/* Setup state */
+	unsigned int se_cntl_status;			/* 0x2140 */
+
+#ifdef TCL_ENABLE
+	/* TCL state */
+	radeon_color_regs_t se_tcl_material_emmissive;	/* 0x2210 */
+	radeon_color_regs_t se_tcl_material_ambient;
+	radeon_color_regs_t se_tcl_material_diffuse;
+	radeon_color_regs_t se_tcl_material_specular;
+	unsigned int se_tcl_shininess;
+	unsigned int se_tcl_output_vtx_fmt;
+	unsigned int se_tcl_output_vtx_sel;
+	unsigned int se_tcl_matrix_select_0;
+	unsigned int se_tcl_matrix_select_1;
+	unsigned int se_tcl_ucp_vert_blend_ctl;
+	unsigned int se_tcl_texture_proc_ctl;
+	unsigned int se_tcl_light_model_ctl;
+	unsigned int se_tcl_per_light_ctl[4];
+#endif
+
+	/* Misc state */
+	unsigned int re_top_left;			/* 0x26c0 */
+	unsigned int re_misc;
+} drm_radeon_context_regs_t;
+
+/* Setup registers for each texture unit
+ */
+typedef struct {
+	unsigned int pp_txfilter;
+	unsigned int pp_txformat;
+	unsigned int pp_txoffset;
+	unsigned int pp_txcblend;
+	unsigned int pp_txablend;
+	unsigned int pp_tfactor;
+
+	unsigned int pp_border_color;
+
+#ifdef CUBIC_ENABLE
+	unsigned int pp_cubic_faces;
+	unsigned int pp_cubic_offset[5];
+#endif
+} drm_radeon_texture_regs_t;
+
+typedef struct {
+	unsigned char next, prev;
+	unsigned char in_use;
+	int age;
+} drm_radeon_tex_region_t;
+
+typedef struct {
+	/* The channel for communication of state information to the kernel
+	 * on firing a vertex buffer.
+	 */
+	drm_radeon_context_regs_t context_state;
+	drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS];
+	unsigned int dirty;
+	unsigned int vertsize;
+	unsigned int vc_format;
+
+	/* The current cliprects, or a subset thereof.
+	 */
+	drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS];
+	unsigned int nbox;
+
+	/* Counters for client-side throttling of rendering clients.
+	 */
+	unsigned int last_frame;
+	unsigned int last_dispatch;
+	unsigned int last_clear;
+
+	drm_radeon_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
+	int tex_age[RADEON_NR_TEX_HEAPS];
+	int ctx_owner;
+} drm_radeon_sarea_t;
+
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmRadeon.h)
+ */
+typedef struct drm_radeon_init {
+	enum {
+		RADEON_INIT_CP    = 0x01,
+		RADEON_CLEANUP_CP = 0x02
+	} func;
+	int sarea_priv_offset;
+	int is_pci;
+	int cp_mode;
+	int agp_size;
+	int ring_size;
+	int usec_timeout;
+
+	unsigned int fb_bpp;
+	unsigned int front_offset, front_pitch;
+	unsigned int back_offset, back_pitch;
+	unsigned int depth_bpp;
+	unsigned int depth_offset, depth_pitch;
+
+	unsigned int fb_offset;
+	unsigned int mmio_offset;
+	unsigned int ring_offset;
+	unsigned int ring_rptr_offset;
+	unsigned int buffers_offset;
+	unsigned int agp_textures_offset;
+} drm_radeon_init_t;
+
+typedef struct drm_radeon_cp_stop {
+	int flush;
+	int idle;
+} drm_radeon_cp_stop_t;
+
+typedef struct drm_radeon_fullscreen {
+	enum {
+		RADEON_INIT_FULLSCREEN    = 0x01,
+		RADEON_CLEANUP_FULLSCREEN = 0x02
+	} func;
+} drm_radeon_fullscreen_t;
+
+#define CLEAR_X1	0
+#define CLEAR_Y1	1
+#define CLEAR_X2	2
+#define CLEAR_Y2	3
+#define CLEAR_DEPTH	4
+
+typedef struct drm_radeon_clear {
+	unsigned int flags;
+	int x, y, w, h;
+	unsigned int clear_color;
+	unsigned int clear_depth;
+	union {
+		float f[5];
+		unsigned int ui[5];
+	} rect;
+} drm_radeon_clear_t;
+
+typedef struct drm_radeon_vertex {
+	int prim;
+	int idx;			/* Index of vertex buffer */
+	int count;			/* Number of vertices in buffer */
+	int discard;			/* Client finished with buffer? */
+} drm_radeon_vertex_t;
+
+typedef struct drm_radeon_indices {
+	int prim;
+	int idx;
+	int start;
+	int end;
+	int discard;			/* Client finished with buffer? */
+} drm_radeon_indices_t;
+
+typedef struct drm_radeon_blit {
+	int idx;
+	int pitch;
+	int offset;
+	int format;
+	unsigned short x, y;
+	unsigned short width, height;
+} drm_radeon_blit_t;
+
+typedef struct drm_radeon_stipple {
+	unsigned int *mask;
+} drm_radeon_stipple_t;
+
+typedef struct drm_radeon_indirect {
+	int idx;
+	int start;
+	int end;
+	int discard;
+} drm_radeon_indirect_t;
+
+#endif
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/radeon_drv.c linux/drivers/char/drm/radeon_drv.c
--- v2.4.0/linux/drivers/char/drm/radeon_drv.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/radeon_drv.c	Fri Jan 19 13:34:08 2001
@@ -0,0 +1,702 @@
+/* radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Kevin E. Martin <martin@valinux.com>
+ *          Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+#include <linux/config.h>
+#include "drmP.h"
+#include "radeon_drv.h"
+
+#define RADEON_NAME		"radeon"
+#define RADEON_DESC		"ATI Radeon"
+#define RADEON_DATE		"20010105"
+#define RADEON_MAJOR		1
+#define RADEON_MINOR		0
+#define RADEON_PATCHLEVEL	0
+
+static drm_device_t	      radeon_device;
+drm_ctx_t	              radeon_res_ctx;
+
+static struct file_operations radeon_fops = {
+#if LINUX_VERSION_CODE >= 0x020400
+				/* This started being used during 2.4.0-test */
+	owner:   THIS_MODULE,
+#endif
+	open:	 radeon_open,
+	flush:	 drm_flush,
+	release: radeon_release,
+	ioctl:	 radeon_ioctl,
+	mmap:	 drm_mmap,
+	read:	 drm_read,
+	fasync:	 drm_fasync,
+	poll:	 drm_poll,
+};
+
+static struct miscdevice      radeon_misc = {
+	minor: MISC_DYNAMIC_MINOR,
+	name:  RADEON_NAME,
+	fops:  &radeon_fops,
+};
+
+static drm_ioctl_desc_t	      radeon_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { radeon_version,	0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { drm_getunique,	0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { drm_getmagic,	0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { drm_irq_busid,	0, 1 },
+
+	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]    = { drm_setunique,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]	        = { drm_block,		1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]       = { drm_unblock,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]    = { drm_authmagic,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { drm_addmap,		1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]      = { radeon_addbufs,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]     = { drm_markbufs,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { drm_infobufs,	1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { radeon_mapbufs,	1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { drm_freebufs,	1, 0 },
+
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]       = { radeon_addctx,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]        = { radeon_rmctx,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]       = { radeon_modctx,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]       = { radeon_getctx,	1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]    = { radeon_switchctx,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]       = { radeon_newctx,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]       = { radeon_resctx,	1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]      = { drm_adddraw,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]       = { drm_rmdraw,		1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	        = { radeon_cp_buffers,	1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	        = { radeon_lock,	1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]        = { radeon_unlock,	1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { drm_finish,		1, 0 },
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { drm_agp_acquire,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { drm_agp_release,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { drm_agp_enable,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { drm_agp_info,	1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = { drm_agp_alloc,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = { drm_agp_free,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = { drm_agp_bind,	1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { drm_agp_unbind,	1, 1 },
+#endif
+
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)]  = { radeon_cp_init,   1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)] = { radeon_cp_start,  1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)]  = { radeon_cp_stop,   1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset,  1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)]  = { radeon_cp_idle,   1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 },
+
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)]    = { radeon_cp_swap,    1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)]   = { radeon_cp_clear,   1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)]  = { radeon_cp_vertex,  1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_BLIT)]    = { radeon_cp_blit,    1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)]= { radeon_cp_indirect,1, 1 },
+};
+#define RADEON_IOCTL_COUNT DRM_ARRAY_SIZE(radeon_ioctls)
+
+#ifdef MODULE
+static char		      *radeon = NULL;
+#endif
+
+MODULE_AUTHOR("VA Linux Systems, Inc.");
+MODULE_DESCRIPTION("radeon");
+MODULE_PARM(radeon, "s");
+
+#ifndef MODULE
+/* radeon_options is called by the kernel to parse command-line options
+ * passed via the boot-loader (e.g., LILO).  It calls the insmod option
+ * routine, drm_parse_drm.
+ */
+
+static int __init radeon_options(char *str)
+{
+	drm_parse_options(str);
+	return 1;
+}
+
+__setup("radeon=", radeon_options);
+#endif
+
+static int radeon_setup(drm_device_t *dev)
+{
+	int i;
+
+	atomic_set(&dev->ioctl_count, 0);
+	atomic_set(&dev->vma_count, 0);
+	dev->buf_use	  = 0;
+	atomic_set(&dev->buf_alloc, 0);
+
+	drm_dma_setup(dev);
+
+	atomic_set(&dev->total_open, 0);
+	atomic_set(&dev->total_close, 0);
+	atomic_set(&dev->total_ioctl, 0);
+	atomic_set(&dev->total_irq, 0);
+	atomic_set(&dev->total_ctx, 0);
+	atomic_set(&dev->total_locks, 0);
+	atomic_set(&dev->total_unlocks, 0);
+	atomic_set(&dev->total_contends, 0);
+	atomic_set(&dev->total_sleeps, 0);
+
+	for (i = 0; i < DRM_HASH_SIZE; i++) {
+		dev->magiclist[i].head = NULL;
+		dev->magiclist[i].tail = NULL;
+	}
+	dev->maplist	    = NULL;
+	dev->map_count	    = 0;
+	dev->vmalist	    = NULL;
+	dev->lock.hw_lock   = NULL;
+	init_waitqueue_head(&dev->lock.lock_queue);
+	dev->queue_count    = 0;
+	dev->queue_reserved = 0;
+	dev->queue_slots    = 0;
+	dev->queuelist	    = NULL;
+	dev->irq	    = 0;
+	dev->context_flag   = 0;
+	dev->interrupt_flag = 0;
+	dev->dma_flag	    = 0;
+	dev->last_context   = 0;
+	dev->last_switch    = 0;
+	dev->last_checked   = 0;
+	init_timer(&dev->timer);
+	init_waitqueue_head(&dev->context_wait);
+
+	dev->ctx_start	    = 0;
+	dev->lck_start	    = 0;
+
+	dev->buf_rp	    = dev->buf;
+	dev->buf_wp	    = dev->buf;
+	dev->buf_end	    = dev->buf + DRM_BSZ;
+	dev->buf_async	    = NULL;
+	init_waitqueue_head(&dev->buf_readers);
+	init_waitqueue_head(&dev->buf_writers);
+
+	radeon_res_ctx.handle = -1;
+
+	DRM_DEBUG("\n");
+
+	/* The kernel's context could be created here, but is now created
+	   in drm_dma_enqueue.	This is more resource-efficient for
+	   hardware that does not do DMA, but may mean that
+	   drm_select_queue fails between the time the interrupt is
+	   initialized and the time the queues are initialized. */
+
+	return 0;
+}
+
+
+static int radeon_takedown(drm_device_t *dev)
+{
+	int		  i;
+	drm_magic_entry_t *pt, *next;
+	drm_map_t	  *map;
+	drm_vma_entry_t	  *vma, *vma_next;
+
+	DRM_DEBUG("\n");
+
+	down(&dev->struct_sem);
+	del_timer(&dev->timer);
+
+	if (dev->devname) {
+		drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
+		dev->devname = NULL;
+	}
+
+	if (dev->unique) {
+		drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
+		dev->unique = NULL;
+		dev->unique_len = 0;
+	}
+				/* Clear pid list */
+	for (i = 0; i < DRM_HASH_SIZE; i++) {
+		for (pt = dev->magiclist[i].head; pt; pt = next) {
+			next = pt->next;
+			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+		}
+		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
+	}
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+				/* Clear AGP information */
+	if (dev->agp) {
+		drm_agp_mem_t *entry;
+		drm_agp_mem_t *nexte;
+
+				/* Remove AGP resources, but leave dev->agp
+                                   intact until radeon_cleanup is called. */
+		for (entry = dev->agp->memory; entry; entry = nexte) {
+			nexte = entry->next;
+			if (entry->bound) drm_unbind_agp(entry->memory);
+			drm_free_agp(entry->memory, entry->pages);
+			drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+		}
+		dev->agp->memory = NULL;
+
+		if (dev->agp->acquired)	_drm_agp_release();
+
+		dev->agp->acquired = 0;
+		dev->agp->enabled  = 0;
+	}
+#endif
+
+				/* Clear vma list (only built for debugging) */
+	if (dev->vmalist) {
+		for (vma = dev->vmalist; vma; vma = vma_next) {
+			vma_next = vma->next;
+			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
+		}
+		dev->vmalist = NULL;
+	}
+
+				/* Clear map area and mtrr information */
+	if (dev->maplist) {
+		for (i = 0; i < dev->map_count; i++) {
+			map = dev->maplist[i];
+			switch (map->type) {
+			case _DRM_REGISTERS:
+			case _DRM_FRAME_BUFFER:
+#ifdef CONFIG_MTRR
+				if (map->mtrr >= 0) {
+					int retcode;
+					retcode = mtrr_del(map->mtrr,
+							   map->offset,
+							   map->size);
+					DRM_DEBUG("mtrr_del = %d\n", retcode);
+				}
+#endif
+				drm_ioremapfree(map->handle, map->size);
+				break;
+			case _DRM_SHM:
+				drm_free_pages((unsigned long)map->handle,
+					       drm_order(map->size)
+					       - PAGE_SHIFT,
+					       DRM_MEM_SAREA);
+				break;
+			case _DRM_AGP:
+				/* Do nothing here, because this is all
+                                   handled in the AGP/GART driver. */
+				break;
+			}
+			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+		}
+		drm_free(dev->maplist,
+			 dev->map_count * sizeof(*dev->maplist),
+			 DRM_MEM_MAPS);
+		dev->maplist   = NULL;
+		dev->map_count = 0;
+	}
+
+	drm_dma_takedown(dev);
+
+	dev->queue_count     = 0;
+	if (dev->lock.hw_lock) {
+		dev->lock.hw_lock    = NULL; /* SHM removed */
+		dev->lock.pid	     = 0;
+		wake_up_interruptible(&dev->lock.lock_queue);
+	}
+	up(&dev->struct_sem);
+
+	return 0;
+}
+
+/* radeon_init is called via init_module at module load time, or via
+ * linux/init/main.c (this is not currently supported). */
+
+static int __init radeon_init(void)
+{
+	int		      retcode;
+	drm_device_t	      *dev = &radeon_device;
+
+	DRM_DEBUG("\n");
+
+	memset((void *)dev, 0, sizeof(*dev));
+	dev->count_lock	  = SPIN_LOCK_UNLOCKED;
+	sema_init(&dev->struct_sem, 1);
+
+#ifdef MODULE
+	drm_parse_options(radeon);
+#endif
+
+	if ((retcode = misc_register(&radeon_misc))) {
+		DRM_ERROR("Cannot register \"%s\"\n", RADEON_NAME);
+		return retcode;
+	}
+	dev->device = MKDEV(MISC_MAJOR, radeon_misc.minor);
+	dev->name   = RADEON_NAME;
+
+	drm_mem_init();
+	drm_proc_init(dev);
+
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+	dev->agp    = drm_agp_init();
+      	if (dev->agp == NULL) {
+	   	DRM_ERROR("Cannot initialize agpgart module.\n");
+	   	drm_proc_cleanup();
+	   	misc_deregister(&radeon_misc);
+	   	radeon_takedown(dev);
+	   	return -ENOMEM;
+	}
+
+#ifdef CONFIG_MTRR
+	dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
+				      dev->agp->agp_info.aper_size*1024*1024,
+				      MTRR_TYPE_WRCOMB,
+				      1);
+#endif
+#endif
+
+	if((retcode = drm_ctxbitmap_init(dev))) {
+		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+		drm_proc_cleanup();
+		misc_deregister(&radeon_misc);
+		radeon_takedown(dev);
+		return retcode;
+	}
+
+	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+		 RADEON_NAME,
+		 RADEON_MAJOR,
+		 RADEON_MINOR,
+		 RADEON_PATCHLEVEL,
+		 RADEON_DATE,
+		 radeon_misc.minor);
+
+	return 0;
+}
+
+/* radeon_cleanup is called via cleanup_module at module unload time. */
+
+static void __exit radeon_cleanup(void)
+{
+	drm_device_t	      *dev = &radeon_device;
+
+	DRM_DEBUG("\n");
+
+	drm_proc_cleanup();
+	if (misc_deregister(&radeon_misc)) {
+		DRM_ERROR("Cannot unload module\n");
+	} else {
+		DRM_INFO("Module unloaded\n");
+	}
+	drm_ctxbitmap_cleanup(dev);
+	radeon_takedown(dev);
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+	if (dev->agp) {
+		drm_agp_uninit();
+		drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
+		dev->agp = NULL;
+	}
+#endif
+}
+
+module_init(radeon_init);
+module_exit(radeon_cleanup);
+
+
+int radeon_version(struct inode *inode, struct file *filp, unsigned int cmd,
+		   unsigned long arg)
+{
+	drm_version_t version;
+	int	      len;
+
+	if (copy_from_user(&version,
+			   (drm_version_t *)arg,
+			   sizeof(version)))
+		return -EFAULT;
+
+#define DRM_COPY(name,value)				     \
+	len = strlen(value);				     \
+	if (len > name##_len) len = name##_len;		     \
+	name##_len = strlen(value);			     \
+	if (len && name) {				     \
+		if (copy_to_user(name, value, len))	     \
+			return -EFAULT;			     \
+	}
+
+	version.version_major	   = RADEON_MAJOR;
+	version.version_minor	   = RADEON_MINOR;
+	version.version_patchlevel = RADEON_PATCHLEVEL;
+
+	DRM_COPY(version.name, RADEON_NAME);
+	DRM_COPY(version.date, RADEON_DATE);
+	DRM_COPY(version.desc, RADEON_DESC);
+
+	if (copy_to_user((drm_version_t *)arg,
+			 &version,
+			 sizeof(version)))
+		return -EFAULT;
+	return 0;
+}
+
+int radeon_open(struct inode *inode, struct file *filp)
+{
+	drm_device_t  *dev    = &radeon_device;
+	int	      retcode = 0;
+
+	DRM_DEBUG("open_count = %d\n", dev->open_count);
+	if (!(retcode = drm_open_helper(inode, filp, dev))) {
+#if LINUX_VERSION_CODE < 0x020333
+		MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
+#endif
+		atomic_inc(&dev->total_open);
+		spin_lock(&dev->count_lock);
+		if (!dev->open_count++) {
+			spin_unlock(&dev->count_lock);
+			return radeon_setup(dev);
+		}
+		spin_unlock(&dev->count_lock);
+	}
+
+	return retcode;
+}
+
+int radeon_release(struct inode *inode, struct file *filp)
+{
+	drm_file_t    *priv   = filp->private_data;
+	drm_device_t  *dev;
+	int	      retcode = 0;
+
+	lock_kernel();
+	dev = priv->dev;
+
+	DRM_DEBUG("open_count = %d\n", dev->open_count);
+
+	/* Force the cleanup of page flipping when required */
+	if ( dev->dev_private ) {
+		drm_radeon_private_t *dev_priv = dev->dev_private;
+		if ( dev_priv->page_flipping ) {
+			radeon_do_cleanup_pageflip( dev );
+		}
+	}
+
+	if (!(retcode = drm_release(inode, filp))) {
+#if LINUX_VERSION_CODE < 0x020333
+		MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
+#endif
+		atomic_inc(&dev->total_close);
+		spin_lock(&dev->count_lock);
+		if (!--dev->open_count) {
+			if (atomic_read(&dev->ioctl_count) || dev->blocked) {
+				DRM_ERROR("Device busy: %d %d\n",
+					  atomic_read(&dev->ioctl_count),
+					  dev->blocked);
+				spin_unlock(&dev->count_lock);
+				unlock_kernel();
+				return -EBUSY;
+			}
+			spin_unlock(&dev->count_lock);
+			unlock_kernel();
+			return radeon_takedown(dev);
+		}
+		spin_unlock(&dev->count_lock);
+	}
+
+	unlock_kernel();
+	return retcode;
+}
+
+/* radeon_ioctl is called whenever a process performs an ioctl on /dev/drm. */
+
+int radeon_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+		 unsigned long arg)
+{
+	int		 nr	 = DRM_IOCTL_NR(cmd);
+	drm_file_t	 *priv	 = filp->private_data;
+	drm_device_t	 *dev	 = priv->dev;
+	int		 retcode = 0;
+	drm_ioctl_desc_t *ioctl;
+	drm_ioctl_t	 *func;
+
+	atomic_inc(&dev->ioctl_count);
+	atomic_inc(&dev->total_ioctl);
+	++priv->ioctl_count;
+
+	DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n",
+		  current->pid, cmd, nr, dev->device, priv->authenticated);
+
+	if (nr >= RADEON_IOCTL_COUNT) {
+		retcode = -EINVAL;
+	} else {
+		ioctl	  = &radeon_ioctls[nr];
+		func	  = ioctl->func;
+
+		if (!func) {
+			DRM_DEBUG("no function\n");
+			retcode = -EINVAL;
+		} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
+			    || (ioctl->auth_needed && !priv->authenticated)) {
+			retcode = -EACCES;
+		} else {
+			retcode = (func)(inode, filp, cmd, arg);
+		}
+	}
+
+	atomic_dec(&dev->ioctl_count);
+	return retcode;
+}
+
+int radeon_lock(struct inode *inode, struct file *filp, unsigned int cmd,
+		unsigned long arg)
+{
+        drm_file_t        *priv   = filp->private_data;
+        drm_device_t      *dev    = priv->dev;
+        DECLARE_WAITQUEUE(entry, current);
+        int               ret   = 0;
+        drm_lock_t        lock;
+#if DRM_DMA_HISTOGRAM
+        cycles_t          start;
+
+        dev->lck_start = start = get_cycles();
+#endif
+
+        if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+		return -EFAULT;
+
+        if (lock.context == DRM_KERNEL_CONTEXT) {
+                DRM_ERROR("Process %d using kernel context %d\n",
+                          current->pid, lock.context);
+                return -EINVAL;
+        }
+
+        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+                  lock.context, current->pid, dev->lock.hw_lock->lock,
+                  lock.flags);
+
+        if (lock.context < 0 /* || lock.context >= dev->queue_count */)
+                return -EINVAL;
+
+        if (!ret) {
+                add_wait_queue(&dev->lock.lock_queue, &entry);
+                for (;;) {
+                        current->state = TASK_INTERRUPTIBLE;
+                        if (!dev->lock.hw_lock) {
+                                /* Device has been unregistered */
+                                ret = -EINTR;
+                                break;
+                        }
+                        if (drm_lock_take(&dev->lock.hw_lock->lock,
+                                          lock.context)) {
+                                dev->lock.pid       = current->pid;
+                                dev->lock.lock_time = jiffies;
+                                atomic_inc(&dev->total_locks);
+                                break;  /* Got lock */
+                        }
+
+                                /* Contention */
+                        atomic_inc(&dev->total_sleeps);
+                        schedule();
+                        if (signal_pending(current)) {
+                                ret = -ERESTARTSYS;
+                                break;
+                        }
+                }
+                current->state = TASK_RUNNING;
+                remove_wait_queue(&dev->lock.lock_queue, &entry);
+        }
+
+        if (!ret) {
+		sigemptyset(&dev->sigmask);
+		sigaddset(&dev->sigmask, SIGSTOP);
+		sigaddset(&dev->sigmask, SIGTSTP);
+		sigaddset(&dev->sigmask, SIGTTIN);
+		sigaddset(&dev->sigmask, SIGTTOU);
+		dev->sigdata.context = lock.context;
+		dev->sigdata.lock    = dev->lock.hw_lock;
+		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+                if (lock.flags & _DRM_LOCK_READY) {
+				/* Wait for space in DMA/FIFO */
+		}
+                if (lock.flags & _DRM_LOCK_QUIESCENT) {
+				/* Make hardware quiescent */
+			DRM_DEBUG("not quiescent!\n");
+#if 0
+                        radeon_quiescent(dev);
+#endif
+		}
+        }
+
+#if LINUX_VERSION_CODE < 0x020400
+	if (lock.context != radeon_res_ctx.handle) {
+		current->counter = 5;
+		current->priority = DEF_PRIORITY/4;
+	}
+#endif
+        DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+
+#if DRM_DMA_HISTOGRAM
+        atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
+#endif
+
+        return ret;
+}
+
+
+int radeon_unlock(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+	drm_file_t	  *priv	  = filp->private_data;
+	drm_device_t	  *dev	  = priv->dev;
+	drm_lock_t	  lock;
+
+	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+		return -EFAULT;
+
+	if (lock.context == DRM_KERNEL_CONTEXT) {
+		DRM_ERROR("Process %d using kernel context %d\n",
+			  current->pid, lock.context);
+		return -EINVAL;
+	}
+
+	DRM_DEBUG("%d frees lock (%d holds)\n",
+		  lock.context,
+		  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+	atomic_inc(&dev->total_unlocks);
+	if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
+		atomic_inc(&dev->total_contends);
+	drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
+				/* FIXME: Try to send data to card here */
+	if (!dev->context_flag) {
+		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
+				  DRM_KERNEL_CONTEXT)) {
+			DRM_ERROR("\n");
+		}
+	}
+
+#if LINUX_VERSION_CODE < 0x020400
+	if (lock.context != radeon_res_ctx.handle) {
+		current->counter = 5;
+		current->priority = DEF_PRIORITY;
+	}
+#endif
+	unblock_all_signals();
+	return 0;
+}
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/radeon_drv.h linux/drivers/char/drm/radeon_drv.h
--- v2.4.0/linux/drivers/char/drm/radeon_drv.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/radeon_drv.h	Fri Jan 19 13:34:09 2001
@@ -0,0 +1,709 @@
+/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Rickard E. (Rik) Faith <faith@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __RADEON_DRV_H__
+#define __RADEON_DRV_H__
+
+typedef struct drm_radeon_freelist {
+   	unsigned int age;
+   	drm_buf_t *buf;
+   	struct drm_radeon_freelist *next;
+   	struct drm_radeon_freelist *prev;
+} drm_radeon_freelist_t;
+
+typedef struct drm_radeon_ring_buffer {
+	u32 *start;
+	u32 *end;
+	int size;
+	int size_l2qw;
+
+	volatile u32 *head;
+	u32 tail;
+	u32 tail_mask;
+	int space;
+} drm_radeon_ring_buffer_t;
+
+typedef struct drm_radeon_depth_clear_t {
+	u32 rb3d_cntl;
+	u32 rb3d_zstencilcntl;
+	u32 se_cntl;
+} drm_radeon_depth_clear_t;
+
+typedef struct drm_radeon_private {
+	drm_radeon_ring_buffer_t ring;
+	drm_radeon_sarea_t *sarea_priv;
+
+	int agp_size;
+	u32 agp_vm_start;
+	u32 agp_buffers_offset;
+
+	int cp_mode;
+	int cp_running;
+
+   	drm_radeon_freelist_t *head;
+   	drm_radeon_freelist_t *tail;
+/* FIXME: ROTATE_BUFS is a hask to cycle through bufs until freelist
+   code is used.  Note this hides a problem with the scratch register
+   (used to keep track of last buffer completed) being written to before
+   the last buffer has actually completed rendering. */
+#define ROTATE_BUFS 1
+#if ROTATE_BUFS
+	int last_buf;
+#endif
+	volatile u32 *scratch;
+
+	int usec_timeout;
+	int is_pci;
+
+	atomic_t idle_count;
+
+	int page_flipping;
+	int current_page;
+	u32 crtc_offset;
+	u32 crtc_offset_cntl;
+
+	unsigned int color_fmt;
+	unsigned int front_offset;
+	unsigned int front_pitch;
+	unsigned int back_offset;
+	unsigned int back_pitch;
+
+	unsigned int depth_fmt;
+	unsigned int depth_offset;
+	unsigned int depth_pitch;
+
+	u32 front_pitch_offset;
+	u32 back_pitch_offset;
+	u32 depth_pitch_offset;
+
+	drm_radeon_depth_clear_t depth_clear;
+
+	drm_map_t *sarea;
+	drm_map_t *fb;
+	drm_map_t *mmio;
+	drm_map_t *cp_ring;
+	drm_map_t *ring_rptr;
+	drm_map_t *buffers;
+	drm_map_t *agp_textures;
+} drm_radeon_private_t;
+
+typedef struct drm_radeon_buf_priv {
+	u32 age;
+	int prim;
+	int discard;
+	int dispatched;
+   	drm_radeon_freelist_t *list_entry;
+} drm_radeon_buf_priv_t;
+
+				/* radeon_drv.c */
+extern int  radeon_version( struct inode *inode, struct file *filp,
+			    unsigned int cmd, unsigned long arg );
+extern int  radeon_open( struct inode *inode, struct file *filp );
+extern int  radeon_release( struct inode *inode, struct file *filp );
+extern int  radeon_ioctl( struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg );
+extern int  radeon_lock( struct inode *inode, struct file *filp,
+			 unsigned int cmd, unsigned long arg );
+extern int  radeon_unlock( struct inode *inode, struct file *filp,
+			   unsigned int cmd, unsigned long arg );
+
+				/* radeon_cp.c */
+extern int radeon_cp_init( struct inode *inode, struct file *filp,
+			   unsigned int cmd, unsigned long arg );
+extern int radeon_cp_start( struct inode *inode, struct file *filp,
+			    unsigned int cmd, unsigned long arg );
+extern int radeon_cp_stop( struct inode *inode, struct file *filp,
+			   unsigned int cmd, unsigned long arg );
+extern int radeon_cp_reset( struct inode *inode, struct file *filp,
+			    unsigned int cmd, unsigned long arg );
+extern int radeon_cp_idle( struct inode *inode, struct file *filp,
+			   unsigned int cmd, unsigned long arg );
+extern int radeon_engine_reset( struct inode *inode, struct file *filp,
+				unsigned int cmd, unsigned long arg );
+extern int radeon_fullscreen( struct inode *inode, struct file *filp,
+			      unsigned int cmd, unsigned long arg );
+extern int radeon_cp_buffers( struct inode *inode, struct file *filp,
+			      unsigned int cmd, unsigned long arg );
+
+extern void radeon_freelist_reset( drm_device_t *dev );
+extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
+
+extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
+extern void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv );
+
+extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
+extern int radeon_do_cleanup_pageflip( drm_device_t *dev );
+
+				/* radeon_state.c */
+extern int radeon_cp_clear( struct inode *inode, struct file *filp,
+			    unsigned int cmd, unsigned long arg );
+extern int radeon_cp_swap( struct inode *inode, struct file *filp,
+			   unsigned int cmd, unsigned long arg );
+extern int radeon_cp_vertex( struct inode *inode, struct file *filp,
+			     unsigned int cmd, unsigned long arg );
+extern int radeon_cp_indices( struct inode *inode, struct file *filp,
+			      unsigned int cmd, unsigned long arg );
+extern int radeon_cp_blit( struct inode *inode, struct file *filp,
+			   unsigned int cmd, unsigned long arg );
+extern int radeon_cp_stipple( struct inode *inode, struct file *filp,
+			      unsigned int cmd, unsigned long arg );
+extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
+			       unsigned int cmd, unsigned long arg );
+
+				/* radeon_bufs.c */
+extern int radeon_addbufs(struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg);
+extern int radeon_mapbufs(struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg);
+
+				/* radeon_context.c */
+extern int  radeon_resctx(struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg);
+extern int  radeon_addctx(struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg);
+extern int  radeon_modctx(struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg);
+extern int  radeon_getctx(struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg);
+extern int  radeon_switchctx(struct inode *inode, struct file *filp,
+			     unsigned int cmd, unsigned long arg);
+extern int  radeon_newctx(struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg);
+extern int  radeon_rmctx(struct inode *inode, struct file *filp,
+			 unsigned int cmd, unsigned long arg);
+
+extern int  radeon_context_switch(drm_device_t *dev, int old, int new);
+extern int  radeon_context_switch_complete(drm_device_t *dev, int new);
+
+
+/* Register definitions, register access macros and drmAddMap constants
+ * for Radeon kernel driver.
+ */
+
+#define RADEON_AUX_SCISSOR_CNTL		0x26f0
+#	define RADEON_EXCLUSIVE_SCISSOR_0	(1 << 24)
+#	define RADEON_EXCLUSIVE_SCISSOR_1	(1 << 25)
+#	define RADEON_EXCLUSIVE_SCISSOR_2	(1 << 26)
+#	define RADEON_SCISSOR_0_ENABLE		(1 << 28)
+#	define RADEON_SCISSOR_1_ENABLE		(1 << 29)
+#	define RADEON_SCISSOR_2_ENABLE		(1 << 30)
+
+#define RADEON_BUS_CNTL			0x0030
+#	define RADEON_BUS_MASTER_DIS		(1 << 6)
+
+#define RADEON_CLOCK_CNTL_DATA		0x000c
+#	define RADEON_PLL_WR_EN			(1 << 7)
+#define RADEON_CLOCK_CNTL_INDEX		0x0008
+#define RADEON_CONFIG_APER_SIZE		0x0108
+#define RADEON_CRTC_OFFSET		0x0224
+#define RADEON_CRTC_OFFSET_CNTL		0x0228
+#	define RADEON_CRTC_TILE_EN		(1 << 15)
+#	define RADEON_CRTC_OFFSET_FLIP_CNTL	(1 << 16)
+
+#define RADEON_RB3D_COLORPITCH		0x1c48
+#define RADEON_RB3D_DEPTHCLEARVALUE	0x1c30
+#define RADEON_RB3D_DEPTHXY_OFFSET	0x1c60
+
+#define RADEON_DP_GUI_MASTER_CNTL	0x146c
+#	define RADEON_GMC_SRC_PITCH_OFFSET_CNTL	(1 << 0)
+#	define RADEON_GMC_DST_PITCH_OFFSET_CNTL	(1 << 1)
+#	define RADEON_GMC_BRUSH_SOLID_COLOR	(13 << 4)
+#	define RADEON_GMC_BRUSH_NONE		(15 << 4)
+#	define RADEON_GMC_DST_16BPP		(4 << 8)
+#	define RADEON_GMC_DST_24BPP		(5 << 8)
+#	define RADEON_GMC_DST_32BPP		(6 << 8)
+#	define RADEON_GMC_DST_DATATYPE_SHIFT	8
+#	define RADEON_GMC_SRC_DATATYPE_COLOR	(3 << 12)
+#	define RADEON_DP_SRC_SOURCE_MEMORY	(2 << 24)
+#	define RADEON_DP_SRC_SOURCE_HOST_DATA	(3 << 24)
+#	define RADEON_GMC_CLR_CMP_CNTL_DIS	(1 << 28)
+#	define RADEON_GMC_WR_MSK_DIS		(1 << 30)
+#	define RADEON_ROP3_S			0x00cc0000
+#	define RADEON_ROP3_P			0x00f00000
+#define RADEON_DP_WRITE_MASK		0x16cc
+#define RADEON_DST_PITCH_OFFSET		0x142c
+#define RADEON_DST_PITCH_OFFSET_C	0x1c80
+#	define RADEON_DST_TILE_LINEAR		(0 << 30)
+#	define RADEON_DST_TILE_MACRO		(1 << 30)
+#	define RADEON_DST_TILE_MICRO		(2 << 30)
+#	define RADEON_DST_TILE_BOTH		(3 << 30)
+
+#define RADEON_SCRATCH_REG0		0x15e0
+#define RADEON_SCRATCH_REG1		0x15e4
+#define RADEON_SCRATCH_REG2		0x15e8
+#define RADEON_SCRATCH_REG3		0x15ec
+#define RADEON_SCRATCH_REG4		0x15f0
+#define RADEON_SCRATCH_REG5		0x15f4
+#define RADEON_SCRATCH_UMSK		0x0770
+#define RADEON_SCRATCH_ADDR		0x0774
+
+#define RADEON_HOST_PATH_CNTL		0x0130
+#	define RADEON_HDP_SOFT_RESET		(1 << 26)
+#	define RADEON_HDP_WC_TIMEOUT_MASK	(7 << 28)
+#	define RADEON_HDP_WC_TIMEOUT_28BCLK	(7 << 28)
+
+#define RADEON_ISYNC_CNTL		0x1724
+#	define RADEON_ISYNC_ANY2D_IDLE3D	(1 << 0)
+#	define RADEON_ISYNC_ANY3D_IDLE2D	(1 << 1)
+#	define RADEON_ISYNC_TRIG2D_IDLE3D	(1 << 2)
+#	define RADEON_ISYNC_TRIG3D_IDLE2D	(1 << 3)
+#	define RADEON_ISYNC_WAIT_IDLEGUI	(1 << 4)
+#	define RADEON_ISYNC_CPSCRATCH_IDLEGUI	(1 << 5)
+
+#define RADEON_MC_AGP_LOCATION		0x014c
+#define RADEON_MC_FB_LOCATION		0x0148
+#define RADEON_MCLK_CNTL		0x0012
+
+#define RADEON_PP_BORDER_COLOR_0	0x1d40
+#define RADEON_PP_BORDER_COLOR_1	0x1d44
+#define RADEON_PP_BORDER_COLOR_2	0x1d48
+#define RADEON_PP_CNTL			0x1c38
+#	define RADEON_SCISSOR_ENABLE		(1 <<  1)
+#define RADEON_PP_LUM_MATRIX		0x1d00
+#define RADEON_PP_MISC			0x1c14
+#define RADEON_PP_ROT_MATRIX_0		0x1d58
+#define RADEON_PP_TXFILTER_0		0x1c54
+#define RADEON_PP_TXFILTER_1		0x1c6c
+#define RADEON_PP_TXFILTER_2		0x1c84
+
+#define RADEON_RB2D_DSTCACHE_CTLSTAT	0x342c
+#	define RADEON_RB2D_DC_FLUSH		(3 << 0)
+#	define RADEON_RB2D_DC_FREE		(3 << 2)
+#	define RADEON_RB2D_DC_FLUSH_ALL		0xf
+#	define RADEON_RB2D_DC_BUSY		(1 << 31)
+#define RADEON_RB3D_CNTL		0x1c3c
+#	define RADEON_ALPHA_BLEND_ENABLE	(1 << 0)
+#	define RADEON_PLANE_MASK_ENABLE		(1 << 1)
+#	define RADEON_DITHER_ENABLE		(1 << 2)
+#	define RADEON_ROUND_ENABLE		(1 << 3)
+#	define RADEON_SCALE_DITHER_ENABLE	(1 << 4)
+#	define RADEON_DITHER_INIT		(1 << 5)
+#	define RADEON_ROP_ENABLE		(1 << 6)
+#	define RADEON_STENCIL_ENABLE		(1 << 7)
+#	define RADEON_Z_ENABLE			(1 << 8)
+#	define RADEON_DEPTH_XZ_OFFEST_ENABLE	(1 << 9)
+#	define RADEON_ZBLOCK8			(0 << 15)
+#	define RADEON_ZBLOCK16			(1 << 15)
+#define RADEON_RB3D_DEPTHOFFSET		0x1c24
+#define RADEON_RB3D_PLANEMASK		0x1d84
+#define RADEON_RB3D_STENCILREFMASK	0x1d7c
+#define RADEON_RB3D_ZCACHE_MODE		0x3250
+#define RADEON_RB3D_ZCACHE_CTLSTAT	0x3254
+#	define RADEON_RB3D_ZC_FLUSH		(1 << 0)
+#	define RADEON_RB3D_ZC_FREE		(1 << 2)
+#	define RADEON_RB3D_ZC_FLUSH_ALL		0x5
+#	define RADEON_RB3D_ZC_BUSY		(1 << 31)
+#define RADEON_RB3D_ZSTENCILCNTL	0x1c2c
+#	define RADEON_Z_TEST_MASK		(7 << 4)
+#	define RADEON_Z_TEST_ALWAYS		(7 << 4)
+#	define RADEON_STENCIL_TEST_ALWAYS	(7 << 12)
+#	define RADEON_STENCIL_S_FAIL_KEEP	(0 << 16)
+#	define RADEON_STENCIL_ZPASS_KEEP	(0 << 20)
+#	define RADEON_STENCIL_ZFAIL_KEEP	(0 << 20)
+#	define RADEON_Z_WRITE_ENABLE		(1 << 30)
+#define RADEON_RBBM_SOFT_RESET		0x00f0
+#	define RADEON_SOFT_RESET_CP		(1 <<  0)
+#	define RADEON_SOFT_RESET_HI		(1 <<  1)
+#	define RADEON_SOFT_RESET_SE		(1 <<  2)
+#	define RADEON_SOFT_RESET_RE		(1 <<  3)
+#	define RADEON_SOFT_RESET_PP		(1 <<  4)
+#	define RADEON_SOFT_RESET_E2		(1 <<  5)
+#	define RADEON_SOFT_RESET_RB		(1 <<  6)
+#	define RADEON_SOFT_RESET_HDP		(1 <<  7)
+#define RADEON_RBBM_STATUS		0x0e40
+#	define RADEON_RBBM_FIFOCNT_MASK		0x007f
+#	define RADEON_RBBM_ACTIVE		(1 << 31)
+#define RADEON_RE_LINE_PATTERN		0x1cd0
+#define RADEON_RE_MISC			0x26c4
+#define RADEON_RE_TOP_LEFT		0x26c0
+#define RADEON_RE_WIDTH_HEIGHT		0x1c44
+#define RADEON_RE_STIPPLE_ADDR		0x1cc8
+#define RADEON_RE_STIPPLE_DATA		0x1ccc
+
+#define RADEON_SCISSOR_TL_0		0x1cd8
+#define RADEON_SCISSOR_BR_0		0x1cdc
+#define RADEON_SCISSOR_TL_1		0x1ce0
+#define RADEON_SCISSOR_BR_1		0x1ce4
+#define RADEON_SCISSOR_TL_2		0x1ce8
+#define RADEON_SCISSOR_BR_2		0x1cec
+#define RADEON_SE_COORD_FMT		0x1c50
+#define RADEON_SE_CNTL			0x1c4c
+#	define RADEON_FFACE_CULL_CW		(0 << 0)
+#	define RADEON_BFACE_SOLID		(3 << 1)
+#	define RADEON_FFACE_SOLID		(3 << 3)
+#	define RADEON_FLAT_SHADE_VTX_LAST	(3 << 6)
+#	define RADEON_DIFFUSE_SHADE_FLAT	(1 << 8)
+#	define RADEON_DIFFUSE_SHADE_GOURAUD	(2 << 8)
+#	define RADEON_ALPHA_SHADE_FLAT		(1 << 10)
+#	define RADEON_ALPHA_SHADE_GOURAUD	(2 << 10)
+#	define RADEON_SPECULAR_SHADE_FLAT	(1 << 12)
+#	define RADEON_SPECULAR_SHADE_GOURAUD	(2 << 12)
+#	define RADEON_FOG_SHADE_FLAT		(1 << 14)
+#	define RADEON_FOG_SHADE_GOURAUD		(2 << 14)
+#	define RADEON_VPORT_XY_XFORM_ENABLE	(1 << 24)
+#	define RADEON_VPORT_Z_XFORM_ENABLE	(1 << 25)
+#	define RADEON_VTX_PIX_CENTER_OGL	(1 << 27)
+#	define RADEON_ROUND_MODE_TRUNC		(0 << 28)
+#	define RADEON_ROUND_PREC_8TH_PIX	(1 << 30)
+#define RADEON_SE_CNTL_STATUS		0x2140
+#define RADEON_SE_LINE_WIDTH		0x1db8
+#define RADEON_SE_VPORT_XSCALE		0x1d98
+#define RADEON_SURFACE_ACCESS_FLAGS	0x0bf8
+#define RADEON_SURFACE_ACCESS_CLR	0x0bfc
+#define RADEON_SURFACE_CNTL		0x0b00
+#	define RADEON_SURF_TRANSLATION_DIS	(1 << 8)
+#	define RADEON_NONSURF_AP0_SWP_MASK	(3 << 20)
+#	define RADEON_NONSURF_AP0_SWP_LITTLE	(0 << 20)
+#	define RADEON_NONSURF_AP0_SWP_BIG16	(1 << 20)
+#	define RADEON_NONSURF_AP0_SWP_BIG32	(2 << 20)
+#	define RADEON_NONSURF_AP1_SWP_MASK	(3 << 22)
+#	define RADEON_NONSURF_AP1_SWP_LITTLE	(0 << 22)
+#	define RADEON_NONSURF_AP1_SWP_BIG16	(1 << 22)
+#	define RADEON_NONSURF_AP1_SWP_BIG32	(2 << 22)
+#define RADEON_SURFACE0_INFO		0x0b0c
+#	define RADEON_SURF_PITCHSEL_MASK	(0x1ff << 0)
+#	define RADEON_SURF_TILE_MODE_MASK	(3 << 16)
+#	define RADEON_SURF_TILE_MODE_MACRO	(0 << 16)
+#	define RADEON_SURF_TILE_MODE_MICRO	(1 << 16)
+#	define RADEON_SURF_TILE_MODE_32BIT_Z	(2 << 16)
+#	define RADEON_SURF_TILE_MODE_16BIT_Z	(3 << 16)
+#define RADEON_SURFACE0_LOWER_BOUND	0x0b04
+#define RADEON_SURFACE0_UPPER_BOUND	0x0b08
+#define RADEON_SURFACE1_INFO		0x0b1c
+#define RADEON_SURFACE1_LOWER_BOUND	0x0b14
+#define RADEON_SURFACE1_UPPER_BOUND	0x0b18
+#define RADEON_SURFACE2_INFO		0x0b2c
+#define RADEON_SURFACE2_LOWER_BOUND	0x0b24
+#define RADEON_SURFACE2_UPPER_BOUND	0x0b28
+#define RADEON_SURFACE3_INFO		0x0b3c
+#define RADEON_SURFACE3_LOWER_BOUND	0x0b34
+#define RADEON_SURFACE3_UPPER_BOUND	0x0b38
+#define RADEON_SURFACE4_INFO		0x0b4c
+#define RADEON_SURFACE4_LOWER_BOUND	0x0b44
+#define RADEON_SURFACE4_UPPER_BOUND	0x0b48
+#define RADEON_SURFACE5_INFO		0x0b5c
+#define RADEON_SURFACE5_LOWER_BOUND	0x0b54
+#define RADEON_SURFACE5_UPPER_BOUND	0x0b58
+#define RADEON_SURFACE6_INFO		0x0b6c
+#define RADEON_SURFACE6_LOWER_BOUND	0x0b64
+#define RADEON_SURFACE6_UPPER_BOUND	0x0b68
+#define RADEON_SURFACE7_INFO		0x0b7c
+#define RADEON_SURFACE7_LOWER_BOUND	0x0b74
+#define RADEON_SURFACE7_UPPER_BOUND	0x0b78
+#define RADEON_SW_SEMAPHORE		0x013c
+
+#define RADEON_WAIT_UNTIL		0x1720
+#	define RADEON_WAIT_CRTC_PFLIP		(1 << 0)
+#	define RADEON_WAIT_2D_IDLECLEAN		(1 << 16)
+#	define RADEON_WAIT_3D_IDLECLEAN		(1 << 17)
+#	define RADEON_WAIT_HOST_IDLECLEAN	(1 << 18)
+
+#define RADEON_RB3D_ZMASKOFFSET		0x1c34
+#define RADEON_RB3D_ZSTENCILCNTL	0x1c2c
+#	define RADEON_DEPTH_FORMAT_16BIT_INT_Z	(0 << 0)
+#	define RADEON_DEPTH_FORMAT_24BIT_INT_Z	(2 << 0)
+
+
+/* CP registers */
+#define RADEON_CP_ME_RAM_ADDR		0x07d4
+#define RADEON_CP_ME_RAM_RADDR		0x07d8
+#define RADEON_CP_ME_RAM_DATAH		0x07dc
+#define RADEON_CP_ME_RAM_DATAL		0x07e0
+
+#define RADEON_CP_RB_BASE		0x0700
+#define RADEON_CP_RB_CNTL		0x0704
+#define RADEON_CP_RB_RPTR_ADDR		0x070c
+#define RADEON_CP_RB_RPTR		0x0710
+#define RADEON_CP_RB_WPTR		0x0714
+
+#define RADEON_CP_RB_WPTR_DELAY		0x0718
+#	define RADEON_PRE_WRITE_TIMER_SHIFT	0
+#	define RADEON_PRE_WRITE_LIMIT_SHIFT	23
+
+#define RADEON_CP_IB_BASE		0x0738
+
+#define RADEON_CP_CSQ_CNTL		0x0740
+#	define RADEON_CSQ_CNT_PRIMARY_MASK	(0xff << 0)
+#	define RADEON_CSQ_PRIDIS_INDDIS		(0 << 28)
+#	define RADEON_CSQ_PRIPIO_INDDIS		(1 << 28)
+#	define RADEON_CSQ_PRIBM_INDDIS		(2 << 28)
+#	define RADEON_CSQ_PRIPIO_INDBM		(3 << 28)
+#	define RADEON_CSQ_PRIBM_INDBM		(4 << 28)
+#	define RADEON_CSQ_PRIPIO_INDPIO		(15 << 28)
+
+#define RADEON_AIC_CNTL			0x01d0
+#	define RADEON_PCIGART_TRANSLATE_EN	(1 << 0)
+
+/* CP command packets */
+#define RADEON_CP_PACKET0		0x00000000
+#	define RADEON_ONE_REG_WR		(1 << 15)
+#define RADEON_CP_PACKET1		0x40000000
+#define RADEON_CP_PACKET2		0x80000000
+#define RADEON_CP_PACKET3		0xC0000000
+#	define RADEON_3D_RNDR_GEN_INDX_PRIM	0x00002300
+#	define RADEON_WAIT_FOR_IDLE		0x00002600
+#	define RADEON_3D_DRAW_IMMD		0x00002900
+#	define RADEON_3D_CLEAR_ZMASK		0x00003200
+#	define RADEON_CNTL_HOSTDATA_BLT		0x00009400
+#	define RADEON_CNTL_PAINT_MULTI		0x00009A00
+#	define RADEON_CNTL_BITBLT_MULTI		0x00009B00
+
+#define RADEON_CP_PACKET_MASK		0xC0000000
+#define RADEON_CP_PACKET_COUNT_MASK	0x3fff0000
+#define RADEON_CP_PACKET0_REG_MASK	0x000007ff
+#define RADEON_CP_PACKET1_REG0_MASK	0x000007ff
+#define RADEON_CP_PACKET1_REG1_MASK	0x003ff800
+
+#define RADEON_VTX_Z_PRESENT			(1 << 31)
+
+#define RADEON_PRIM_TYPE_NONE			(0 << 0)
+#define RADEON_PRIM_TYPE_POINT			(1 << 0)
+#define RADEON_PRIM_TYPE_LINE			(2 << 0)
+#define RADEON_PRIM_TYPE_LINE_STRIP		(3 << 0)
+#define RADEON_PRIM_TYPE_TRI_LIST		(4 << 0)
+#define RADEON_PRIM_TYPE_TRI_FAN		(5 << 0)
+#define RADEON_PRIM_TYPE_TRI_STRIP		(6 << 0)
+#define RADEON_PRIM_TYPE_TRI_TYPE2		(7 << 0)
+#define RADEON_PRIM_TYPE_RECT_LIST		(8 << 0)
+#define RADEON_PRIM_TYPE_3VRT_POINT_LIST	(9 << 0)
+#define RADEON_PRIM_TYPE_3VRT_LINE_LIST		(10 << 0)
+#define RADEON_PRIM_WALK_IND			(1 << 4)
+#define RADEON_PRIM_WALK_LIST			(2 << 4)
+#define RADEON_PRIM_WALK_RING			(3 << 4)
+#define RADEON_COLOR_ORDER_BGRA			(0 << 6)
+#define RADEON_COLOR_ORDER_RGBA			(1 << 6)
+#define RADEON_MAOS_ENABLE			(1 << 7)
+#define RADEON_VTX_FMT_R128_MODE		(0 << 8)
+#define RADEON_VTX_FMT_RADEON_MODE		(1 << 8)
+#define RADEON_NUM_VERTICES_SHIFT		16
+
+#define RADEON_COLOR_FORMAT_CI8		2
+#define RADEON_COLOR_FORMAT_ARGB1555	3
+#define RADEON_COLOR_FORMAT_RGB565	4
+#define RADEON_COLOR_FORMAT_ARGB8888	6
+#define RADEON_COLOR_FORMAT_RGB332	7
+#define RADEON_COLOR_FORMAT_RGB8	9
+#define RADEON_COLOR_FORMAT_ARGB4444	15
+
+#define RADEON_TXF_8BPP_I		0
+#define RADEON_TXF_16BPP_AI88		1
+#define RADEON_TXF_8BPP_RGB332		2
+#define RADEON_TXF_16BPP_ARGB1555	3
+#define RADEON_TXF_16BPP_RGB565		4
+#define RADEON_TXF_16BPP_ARGB4444	5
+#define RADEON_TXF_32BPP_ARGB8888	6
+#define RADEON_TXF_32BPP_RGBA8888	7
+
+/* Constants */
+#define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
+
+#define RADEON_LAST_FRAME_REG		RADEON_SCRATCH_REG0
+#define RADEON_LAST_DISPATCH_REG	RADEON_SCRATCH_REG1
+#define RADEON_LAST_CLEAR_REG		RADEON_SCRATCH_REG2
+#define RADEON_LAST_DISPATCH		1
+
+#define RADEON_MAX_VB_AGE		0x7fffffff
+#define RADEON_MAX_VB_VERTS		(0xffff)
+
+
+#define RADEON_BASE(reg)	((u32)(dev_priv->mmio->handle))
+#define RADEON_ADDR(reg)	(RADEON_BASE(reg) + reg)
+
+#define RADEON_DEREF(reg)	*(__volatile__ u32 *)RADEON_ADDR(reg)
+#define RADEON_READ(reg)	RADEON_DEREF(reg)
+#define RADEON_WRITE(reg,val)	do { RADEON_DEREF(reg) = val; } while (0)
+
+#define RADEON_DEREF8(reg)	*(__volatile__ u8 *)RADEON_ADDR(reg)
+#define RADEON_READ8(reg)	RADEON_DEREF8(reg)
+#define RADEON_WRITE8(reg,val)	do { RADEON_DEREF8(reg) = val; } while (0)
+
+#define RADEON_WRITE_PLL(addr,val)                                            \
+do {                                                                          \
+	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX,                                \
+		      ((addr) & 0x1f) | RADEON_PLL_WR_EN);                    \
+	RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val));                          \
+} while (0)
+
+extern int RADEON_READ_PLL(drm_device_t *dev, int addr);
+
+
+
+#define CP_PACKET0( reg, n )						\
+	(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET0_TABLE( reg, n )					\
+	(RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET1( reg0, reg1 )					\
+	(RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2))
+#define CP_PACKET2()							\
+	(RADEON_CP_PACKET2)
+#define CP_PACKET3( pkt, n )						\
+	(RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
+
+
+/* ================================================================
+ * Engine control helper macros
+ */
+
+#define RADEON_WAIT_UNTIL_2D_IDLE()					\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
+		   RADEON_WAIT_HOST_IDLECLEAN) );			\
+} while (0)
+
+#define RADEON_WAIT_UNTIL_3D_IDLE()					\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( (RADEON_WAIT_3D_IDLECLEAN |				\
+		   RADEON_WAIT_HOST_IDLECLEAN) );			\
+} while (0)
+
+#define RADEON_WAIT_UNTIL_IDLE()					\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
+		   RADEON_WAIT_3D_IDLECLEAN |				\
+		   RADEON_WAIT_HOST_IDLECLEAN) );			\
+} while (0)
+
+#define RADEON_WAIT_UNTIL_PAGE_FLIPPED()				\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( RADEON_WAIT_CRTC_PFLIP );				\
+} while (0)
+
+#define RADEON_FLUSH_CACHE()						\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) );	\
+	OUT_RING( RADEON_RB2D_DC_FLUSH );				\
+} while (0)
+
+#define RADEON_PURGE_CACHE()						\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) );	\
+	OUT_RING( RADEON_RB2D_DC_FLUSH_ALL );				\
+} while (0)
+
+#define RADEON_FLUSH_ZCACHE()						\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );	\
+	OUT_RING( RADEON_RB3D_ZC_FLUSH );				\
+} while (0)
+
+#define RADEON_PURGE_ZCACHE()						\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );	\
+	OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL );				\
+} while (0)
+
+
+/* ================================================================
+ * Misc helper macros
+ */
+
+#define VB_AGE_CHECK_WITH_RET( dev_priv )				\
+do {									\
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;		\
+	if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {		\
+		int __ret = radeon_do_cp_idle( dev_priv );		\
+		if ( __ret < 0 ) return __ret;				\
+		sarea_priv->last_dispatch = 0;				\
+		radeon_freelist_reset( dev );				\
+	}								\
+} while (0)
+
+#define RADEON_DISPATCH_AGE( age )					\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) );		\
+	OUT_RING( age );						\
+} while (0)
+
+#define RADEON_FRAME_AGE( age )						\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) );		\
+	OUT_RING( age );						\
+} while (0)
+
+#define RADEON_CLEAR_AGE( age )						\
+do {									\
+	OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) );		\
+	OUT_RING( age );						\
+} while (0)
+
+
+/* ================================================================
+ * Ring control
+ */
+
+#define radeon_flush_write_combine()	mb()
+
+
+#define RADEON_VERBOSE	0
+
+#define RING_LOCALS	int write; unsigned int mask; volatile u32 *ring;
+
+#define BEGIN_RING( n ) do {						\
+	if ( RADEON_VERBOSE ) {						\
+		DRM_INFO( "BEGIN_RING( %d ) in %s\n",			\
+			   n, __FUNCTION__ );				\
+	}								\
+	if ( dev_priv->ring.space < (n) * sizeof(u32) ) {		\
+		radeon_wait_ring( dev_priv, (n) * sizeof(u32) );	\
+	}								\
+	dev_priv->ring.space -= (n) * sizeof(u32);			\
+	ring = dev_priv->ring.start;					\
+	write = dev_priv->ring.tail;					\
+	mask = dev_priv->ring.tail_mask;				\
+} while (0)
+
+#define ADVANCE_RING() do {						\
+	if ( RADEON_VERBOSE ) {						\
+		DRM_INFO( "ADVANCE_RING() tail=0x%06x wr=0x%06x\n",	\
+			  write, dev_priv->ring.tail );			\
+	}								\
+	radeon_flush_write_combine();					\
+	dev_priv->ring.tail = write;					\
+	RADEON_WRITE( RADEON_CP_RB_WPTR, write );			\
+} while (0)
+
+#define OUT_RING( x ) do {						\
+	if ( RADEON_VERBOSE ) {						\
+		DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",		\
+			   (unsigned int)(x), write );			\
+	}								\
+	ring[write++] = (x);						\
+	write &= mask;							\
+} while (0)
+
+#define RADEON_PERFORMANCE_BOXES	0
+
+#endif /* __RADEON_DRV_H__ */
diff -u --recursive --new-file v2.4.0/linux/drivers/char/drm/radeon_state.c linux/drivers/char/drm/radeon_state.c
--- v2.4.0/linux/drivers/char/drm/radeon_state.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/radeon_state.c	Wed Jan 24 09:17:27 2001
@@ -0,0 +1,1447 @@
+/* radeon_state.c -- State support for Radeon -*- linux-c -*-
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "radeon_drv.h"
+#include "drm.h"
+#include <linux/delay.h>
+
+
+/* ================================================================
+ * CP hardware state programming functions
+ */
+
+static inline void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
+					  drm_clip_rect_t *box )
+{
+	RING_LOCALS;
+
+	DRM_DEBUG( "   box:  x1=%d y1=%d  x2=%d y2=%d\n",
+		   box->x1, box->y1, box->x2, box->y2 );
+
+	BEGIN_RING( 4 );
+
+	OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
+	OUT_RING( (box->y1 << 16) | box->x1 );
+
+	OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
+	OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_context( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 14 );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
+	OUT_RING( ctx->pp_misc );
+	OUT_RING( ctx->pp_fog_color );
+	OUT_RING( ctx->re_solid_color );
+	OUT_RING( ctx->rb3d_blendcntl );
+	OUT_RING( ctx->rb3d_depthoffset );
+	OUT_RING( ctx->rb3d_depthpitch );
+	OUT_RING( ctx->rb3d_zstencilcntl );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
+	OUT_RING( ctx->pp_cntl );
+	OUT_RING( ctx->rb3d_cntl );
+	OUT_RING( ctx->rb3d_coloroffset );
+
+	OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
+	OUT_RING( ctx->rb3d_colorpitch );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_vertfmt( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 2 );
+
+	OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
+	OUT_RING( ctx->se_coord_fmt );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_line( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 5 );
+
+	OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
+	OUT_RING( ctx->re_line_pattern );
+	OUT_RING( ctx->re_line_state );
+
+	OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
+	OUT_RING( ctx->se_line_width );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_bumpmap( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 5 );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
+	OUT_RING( ctx->pp_lum_matrix );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
+	OUT_RING( ctx->pp_rot_matrix_0 );
+	OUT_RING( ctx->pp_rot_matrix_1 );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_masks( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 4 );
+
+	OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
+	OUT_RING( ctx->rb3d_stencilrefmask );
+	OUT_RING( ctx->rb3d_ropcntl );
+	OUT_RING( ctx->rb3d_planemask );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_viewport( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 7 );
+
+	OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
+	OUT_RING( ctx->se_vport_xscale );
+	OUT_RING( ctx->se_vport_xoffset );
+	OUT_RING( ctx->se_vport_yscale );
+	OUT_RING( ctx->se_vport_yoffset );
+	OUT_RING( ctx->se_vport_zscale );
+	OUT_RING( ctx->se_vport_zoffset );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_setup( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 4 );
+
+	OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
+	OUT_RING( ctx->se_cntl );
+	OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
+	OUT_RING( ctx->se_cntl_status );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_tcl( drm_radeon_private_t *dev_priv )
+{
+#ifdef TCL_ENABLE
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 29 );
+
+	OUT_RING( CP_PACKET0( RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 27 ) );
+	OUT_RING( ctx->se_tcl_material_emmissive.red );
+	OUT_RING( ctx->se_tcl_material_emmissive.green );
+	OUT_RING( ctx->se_tcl_material_emmissive.blue );
+	OUT_RING( ctx->se_tcl_material_emmissive.alpha );
+	OUT_RING( ctx->se_tcl_material_ambient.red );
+	OUT_RING( ctx->se_tcl_material_ambient.green );
+	OUT_RING( ctx->se_tcl_material_ambient.blue );
+	OUT_RING( ctx->se_tcl_material_ambient.alpha );
+	OUT_RING( ctx->se_tcl_material_diffuse.red );
+	OUT_RING( ctx->se_tcl_material_diffuse.green );
+	OUT_RING( ctx->se_tcl_material_diffuse.blue );
+	OUT_RING( ctx->se_tcl_material_diffuse.alpha );
+	OUT_RING( ctx->se_tcl_material_specular.red );
+	OUT_RING( ctx->se_tcl_material_specular.green );
+	OUT_RING( ctx->se_tcl_material_specular.blue );
+	OUT_RING( ctx->se_tcl_material_specular.alpha );
+	OUT_RING( ctx->se_tcl_shininess );
+	OUT_RING( ctx->se_tcl_output_vtx_fmt );
+	OUT_RING( ctx->se_tcl_output_vtx_sel );
+	OUT_RING( ctx->se_tcl_matrix_select_0 );
+	OUT_RING( ctx->se_tcl_matrix_select_1 );
+	OUT_RING( ctx->se_tcl_ucp_vert_blend_ctl );
+	OUT_RING( ctx->se_tcl_texture_proc_ctl );
+	OUT_RING( ctx->se_tcl_light_model_ctl );
+	for ( i = 0 ; i < 4 ; i++ ) {
+		OUT_RING( ctx->se_tcl_per_light_ctl[i] );
+	}
+
+	ADVANCE_RING();
+#else
+	DRM_ERROR( "TCL not enabled!\n" );
+#endif
+}
+
+static inline void radeon_emit_misc( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 2 );
+
+	OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
+	OUT_RING( ctx->re_misc );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_tex0( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[0];
+	RING_LOCALS;
+	DRM_DEBUG( "    %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
+
+	BEGIN_RING( 9 );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
+	OUT_RING( tex->pp_txfilter );
+	OUT_RING( tex->pp_txformat );
+	OUT_RING( tex->pp_txoffset );
+	OUT_RING( tex->pp_txcblend );
+	OUT_RING( tex->pp_txablend );
+	OUT_RING( tex->pp_tfactor );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
+	OUT_RING( tex->pp_border_color );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_tex1( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[1];
+	RING_LOCALS;
+	DRM_DEBUG( "    %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
+
+	BEGIN_RING( 9 );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
+	OUT_RING( tex->pp_txfilter );
+	OUT_RING( tex->pp_txformat );
+	OUT_RING( tex->pp_txoffset );
+	OUT_RING( tex->pp_txcblend );
+	OUT_RING( tex->pp_txablend );
+	OUT_RING( tex->pp_tfactor );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
+	OUT_RING( tex->pp_border_color );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_tex2( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[2];
+	RING_LOCALS;
+	DRM_DEBUG( "    %s\n", __FUNCTION__ );
+
+	BEGIN_RING( 9 );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
+	OUT_RING( tex->pp_txfilter );
+	OUT_RING( tex->pp_txformat );
+	OUT_RING( tex->pp_txoffset );
+	OUT_RING( tex->pp_txcblend );
+	OUT_RING( tex->pp_txablend );
+	OUT_RING( tex->pp_tfactor );
+
+	OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
+	OUT_RING( tex->pp_border_color );
+
+	ADVANCE_RING();
+}
+
+static inline void radeon_emit_state( drm_radeon_private_t *dev_priv )
+{
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	unsigned int dirty = sarea_priv->dirty;
+
+	DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
+
+	if ( dirty & RADEON_UPLOAD_CONTEXT ) {
+		radeon_emit_context( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_CONTEXT;
+	}
+
+	if ( dirty & RADEON_UPLOAD_VERTFMT ) {
+		radeon_emit_vertfmt( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_VERTFMT;
+	}
+
+	if ( dirty & RADEON_UPLOAD_LINE ) {
+		radeon_emit_line( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_LINE;
+	}
+
+	if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
+		radeon_emit_bumpmap( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_BUMPMAP;
+	}
+
+	if ( dirty & RADEON_UPLOAD_MASKS ) {
+		radeon_emit_masks( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_MASKS;
+	}
+
+	if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
+		radeon_emit_viewport( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_VIEWPORT;
+	}
+
+	if ( dirty & RADEON_UPLOAD_SETUP ) {
+		radeon_emit_setup( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_SETUP;
+	}
+
+	if ( dirty & RADEON_UPLOAD_TCL ) {
+#ifdef TCL_ENABLE
+		radeon_emit_tcl( dev_priv );
+#endif
+		sarea_priv->dirty &= ~RADEON_UPLOAD_TCL;
+	}
+
+	if ( dirty & RADEON_UPLOAD_MISC ) {
+		radeon_emit_misc( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_MISC;
+	}
+
+	if ( dirty & RADEON_UPLOAD_TEX0 ) {
+		radeon_emit_tex0( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_TEX0;
+	}
+
+	if ( dirty & RADEON_UPLOAD_TEX1 ) {
+		radeon_emit_tex1( dev_priv );
+		sarea_priv->dirty &= ~RADEON_UPLOAD_TEX1;
+	}
+
+	if ( dirty & RADEON_UPLOAD_TEX2 ) {
+#if 0
+		radeon_emit_tex2( dev_priv );
+#endif
+		sarea_priv->dirty &= ~RADEON_UPLOAD_TEX2;
+	}
+
+	sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+			       RADEON_UPLOAD_TEX1IMAGES |
+			       RADEON_UPLOAD_TEX2IMAGES |
+			       RADEON_REQUIRE_QUIESCENCE);
+}
+
+
+#if RADEON_PERFORMANCE_BOXES
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void radeon_clear_box( drm_radeon_private_t *dev_priv,
+			      int x, int y, int w, int h,
+			      int r, int g, int b )
+{
+	u32 pitch, offset;
+	u32 color;
+	RING_LOCALS;
+
+	switch ( dev_priv->color_fmt ) {
+	case RADEON_COLOR_FORMAT_RGB565:
+		color = (((r & 0xf8) << 8) |
+			 ((g & 0xfc) << 3) |
+			 ((b & 0xf8) >> 3));
+		break;
+	case RADEON_COLOR_FORMAT_ARGB8888:
+	default:
+		color = (((0xff) << 24) | (r << 16) | (g <<  8) | b);
+		break;
+	}
+
+	offset = dev_priv->back_offset;
+	pitch = dev_priv->back_pitch >> 3;
+
+	BEGIN_RING( 6 );
+
+	OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+	OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+		  RADEON_GMC_BRUSH_SOLID_COLOR |
+		  (dev_priv->color_fmt << 8) |
+		  RADEON_GMC_SRC_DATATYPE_COLOR |
+		  RADEON_ROP3_P |
+		  RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+	OUT_RING( (pitch << 22) | (offset >> 5) );
+	OUT_RING( color );
+
+	OUT_RING( (x << 16) | y );
+	OUT_RING( (w << 16) | h );
+
+	ADVANCE_RING();
+}
+
+static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
+{
+	if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
+		radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
+	} else {
+		atomic_set( &dev_priv->idle_count, 0 );
+	}
+}
+
+#endif
+
+
+/* ================================================================
+ * CP command dispatch functions
+ */
+
+static void radeon_print_dirty( const char *msg, unsigned int flags )
+{
+	DRM_DEBUG( "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+		   msg,
+		   flags,
+		   (flags & RADEON_UPLOAD_CONTEXT)     ? "context, " : "",
+		   (flags & RADEON_UPLOAD_VERTFMT)     ? "vertfmt, " : "",
+		   (flags & RADEON_UPLOAD_LINE)        ? "line, " : "",
+		   (flags & RADEON_UPLOAD_BUMPMAP)     ? "bumpmap, " : "",
+		   (flags & RADEON_UPLOAD_MASKS)       ? "masks, " : "",
+		   (flags & RADEON_UPLOAD_VIEWPORT)    ? "viewport, " : "",
+		   (flags & RADEON_UPLOAD_SETUP)       ? "setup, " : "",
+		   (flags & RADEON_UPLOAD_TCL)         ? "tcl, " : "",
+		   (flags & RADEON_UPLOAD_MISC)        ? "misc, " : "",
+		   (flags & RADEON_UPLOAD_TEX0)        ? "tex0, " : "",
+		   (flags & RADEON_UPLOAD_TEX1)        ? "tex1, " : "",
+		   (flags & RADEON_UPLOAD_TEX2)        ? "tex2, " : "",
+		   (flags & RADEON_UPLOAD_CLIPRECTS)   ? "cliprects, " : "",
+		   (flags & RADEON_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
+}
+
+static void radeon_cp_dispatch_clear( drm_device_t *dev,
+				      drm_radeon_clear_t *clear )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int nbox = sarea_priv->nbox;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	unsigned int flags = clear->flags;
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	radeon_update_ring_snapshot( dev_priv );
+
+	if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
+		unsigned int tmp = flags;
+
+		flags &= ~(RADEON_FRONT | RADEON_BACK);
+		if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK;
+		if ( tmp & RADEON_BACK )  flags |= RADEON_FRONT;
+	}
+
+	for ( i = 0 ; i < nbox ; i++ ) {
+		int x = pbox[i].x1;
+		int y = pbox[i].y1;
+		int w = pbox[i].x2 - x;
+		int h = pbox[i].y2 - y;
+
+		DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
+			   x, y, w, h, flags );
+
+		if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
+			BEGIN_RING( 4 );
+
+			/* Ensure the 3D stream is idle before doing a
+			 * 2D fill to clear the front or back buffer.
+			 */
+			RADEON_WAIT_UNTIL_3D_IDLE();
+
+			OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
+			OUT_RING( sarea_priv->context_state.rb3d_planemask );
+
+			ADVANCE_RING();
+
+			/* Make sure we restore the 3D state next time.
+			 */
+			dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
+							RADEON_UPLOAD_MASKS);
+		}
+
+		if ( flags & RADEON_FRONT ) {
+			BEGIN_RING( 6 );
+
+			OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+			OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+				  RADEON_GMC_BRUSH_SOLID_COLOR |
+				  (dev_priv->color_fmt << 8) |
+				  RADEON_GMC_SRC_DATATYPE_COLOR |
+				  RADEON_ROP3_P |
+				  RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+			OUT_RING( dev_priv->front_pitch_offset );
+			OUT_RING( clear->clear_color );
+
+			OUT_RING( (x << 16) | y );
+			OUT_RING( (w << 16) | h );
+
+			ADVANCE_RING();
+		}
+
+		if ( flags & RADEON_BACK ) {
+			BEGIN_RING( 6 );
+
+			OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+			OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+				  RADEON_GMC_BRUSH_SOLID_COLOR |
+				  (dev_priv->color_fmt << 8) |
+				  RADEON_GMC_SRC_DATATYPE_COLOR |
+				  RADEON_ROP3_P |
+				  RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+			OUT_RING( dev_priv->back_pitch_offset );
+			OUT_RING( clear->clear_color );
+
+			OUT_RING( (x << 16) | y );
+			OUT_RING( (w << 16) | h );
+
+			ADVANCE_RING();
+
+		}
+
+		if ( flags & RADEON_DEPTH ) {
+			drm_radeon_depth_clear_t *depth_clear =
+			   &dev_priv->depth_clear;
+
+			if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+				radeon_emit_state( dev_priv );
+			}
+
+			/* FIXME: Render a rectangle to clear the depth
+			 * buffer.  So much for those "fast Z clears"...
+			 */
+			BEGIN_RING( 23 );
+
+			RADEON_WAIT_UNTIL_2D_IDLE();
+
+			OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
+			OUT_RING( 0x00000000 );
+			OUT_RING( depth_clear->rb3d_cntl );
+			OUT_RING( CP_PACKET0( RADEON_RB3D_ZSTENCILCNTL, 0 ) );
+			OUT_RING( depth_clear->rb3d_zstencilcntl );
+			OUT_RING( CP_PACKET0( RADEON_RB3D_PLANEMASK, 0 ) );
+			OUT_RING( 0x00000000 );
+			OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
+			OUT_RING( depth_clear->se_cntl );
+
+			OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 10 ) );
+			OUT_RING( RADEON_VTX_Z_PRESENT );
+			OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
+				   RADEON_PRIM_WALK_RING |
+				   RADEON_MAOS_ENABLE |
+				   RADEON_VTX_FMT_RADEON_MODE |
+				   (3 << RADEON_NUM_VERTICES_SHIFT)) );
+
+			OUT_RING( clear->rect.ui[CLEAR_X1] );
+			OUT_RING( clear->rect.ui[CLEAR_Y1] );
+			OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+
+			OUT_RING( clear->rect.ui[CLEAR_X1] );
+			OUT_RING( clear->rect.ui[CLEAR_Y2] );
+			OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+
+			OUT_RING( clear->rect.ui[CLEAR_X2] );
+			OUT_RING( clear->rect.ui[CLEAR_Y2] );
+			OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+
+			ADVANCE_RING();
+
+			/* Make sure we restore the 3D state next time.
+			 */
+			dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
+							RADEON_UPLOAD_SETUP |
+							RADEON_UPLOAD_MASKS);
+		}
+	}
+
+	/* Increment the clear counter.  The client-side 3D driver must
+	 * wait on this value before performing the clear ioctl.  We
+	 * need this because the card's so damned fast...
+	 */
+	dev_priv->sarea_priv->last_clear++;
+
+	BEGIN_RING( 4 );
+
+	RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear );
+	RADEON_WAIT_UNTIL_IDLE();
+
+	ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_swap( drm_device_t *dev )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int nbox = sarea_priv->nbox;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	radeon_update_ring_snapshot( dev_priv );
+
+#if RADEON_PERFORMANCE_BOXES
+	/* Do some trivial performance monitoring...
+	 */
+	radeon_cp_performance_boxes( dev_priv );
+#endif
+
+	/* Wait for the 3D stream to idle before dispatching the bitblt.
+	 * This will prevent data corruption between the two streams.
+	 */
+	BEGIN_RING( 2 );
+
+	RADEON_WAIT_UNTIL_3D_IDLE();
+
+	ADVANCE_RING();
+
+	for ( i = 0 ; i < nbox ; i++ ) {
+		int x = pbox[i].x1;
+		int y = pbox[i].y1;
+		int w = pbox[i].x2 - x;
+		int h = pbox[i].y2 - y;
+
+		DRM_DEBUG( "dispatch swap %d,%d-%d,%d\n",
+			   x, y, w, h );
+
+		BEGIN_RING( 7 );
+
+		OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) );
+		OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+			  RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+			  RADEON_GMC_BRUSH_NONE |
+			  (dev_priv->color_fmt << 8) |
+			  RADEON_GMC_SRC_DATATYPE_COLOR |
+			  RADEON_ROP3_S |
+			  RADEON_DP_SRC_SOURCE_MEMORY |
+			  RADEON_GMC_CLR_CMP_CNTL_DIS |
+			  RADEON_GMC_WR_MSK_DIS );
+
+		OUT_RING( dev_priv->back_pitch_offset );
+		OUT_RING( dev_priv->front_pitch_offset );
+
+		OUT_RING( (x << 16) | y );
+		OUT_RING( (x << 16) | y );
+		OUT_RING( (w << 16) | h );
+
+		ADVANCE_RING();
+	}
+
+	/* Increment the frame counter.  The client-side 3D driver must
+	 * throttle the framerate by waiting for this value before
+	 * performing the swapbuffer ioctl.
+	 */
+	dev_priv->sarea_priv->last_frame++;
+
+	BEGIN_RING( 4 );
+
+	RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
+	RADEON_WAIT_UNTIL_2D_IDLE();
+
+	ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_flip( drm_device_t *dev )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+	DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
+
+	radeon_update_ring_snapshot( dev_priv );
+
+#if RADEON_PERFORMANCE_BOXES
+	/* Do some trivial performance monitoring...
+	 */
+	radeon_cp_performance_boxes( dev_priv );
+#endif
+
+	BEGIN_RING( 6 );
+
+	RADEON_WAIT_UNTIL_3D_IDLE();
+	RADEON_WAIT_UNTIL_PAGE_FLIPPED();
+
+	OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) );
+
+	if ( dev_priv->current_page == 0 ) {
+		OUT_RING( dev_priv->back_offset );
+		dev_priv->current_page = 1;
+	} else {
+		OUT_RING( dev_priv->front_offset );
+		dev_priv->current_page = 0;
+	}
+
+	ADVANCE_RING();
+
+	/* Increment the frame counter.  The client-side 3D driver must
+	 * throttle the framerate by waiting for this value before
+	 * performing the swapbuffer ioctl.
+	 */
+	dev_priv->sarea_priv->last_frame++;
+
+	BEGIN_RING( 2 );
+
+	RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
+
+	ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_vertex( drm_device_t *dev,
+				       drm_buf_t *buf )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int format = sarea_priv->vc_format;
+	int offset = dev_priv->agp_buffers_offset + buf->offset;
+	int size = buf->used;
+	int prim = buf_priv->prim;
+	int i = 0;
+	RING_LOCALS;
+	DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox );
+
+	radeon_update_ring_snapshot( dev_priv );
+
+	if ( 0 )
+		radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
+
+	if ( buf->used ) {
+		buf_priv->dispatched = 1;
+
+		if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+			radeon_emit_state( dev_priv );
+		}
+
+		do {
+			/* Emit the next set of up to three cliprects */
+			if ( i < sarea_priv->nbox ) {
+				radeon_emit_clip_rect( dev_priv,
+						       &sarea_priv->boxes[i] );
+			}
+
+			/* Emit the vertex buffer rendering commands */
+			BEGIN_RING( 5 );
+
+			OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
+			OUT_RING( offset );
+			OUT_RING( size );
+			OUT_RING( format );
+			OUT_RING( prim | RADEON_PRIM_WALK_LIST |
+				  RADEON_COLOR_ORDER_RGBA |
+				  RADEON_VTX_FMT_RADEON_MODE |
+				  (size << RADEON_NUM_VERTICES_SHIFT) );
+
+			ADVANCE_RING();
+
+			i++;
+		} while ( i < sarea_priv->nbox );
+	}
+
+	if ( buf_priv->discard ) {
+		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+		/* Emit the vertex buffer age */
+		BEGIN_RING( 2 );
+		RADEON_DISPATCH_AGE( buf_priv->age );
+		ADVANCE_RING();
+
+		buf->pending = 1;
+		buf->used = 0;
+		/* FIXME: Check dispatched field */
+		buf_priv->dispatched = 0;
+	}
+
+	dev_priv->sarea_priv->last_dispatch++;
+
+	sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
+	sarea_priv->nbox = 0;
+}
+
+
+static void radeon_cp_dispatch_indirect( drm_device_t *dev,
+					 drm_buf_t *buf,
+					 int start, int end )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+	RING_LOCALS;
+	DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
+		   buf->idx, start, end );
+
+	radeon_update_ring_snapshot( dev_priv );
+
+	if ( start != end ) {
+		int offset = (dev_priv->agp_buffers_offset
+			      + buf->offset + start);
+		int dwords = (end - start + 3) / sizeof(u32);
+
+		/* Indirect buffer data must be an even number of
+		 * dwords, so if we've been given an odd number we must
+		 * pad the data with a Type-2 CP packet.
+		 */
+		if ( dwords & 1 ) {
+			u32 *data = (u32 *)
+				((char *)dev_priv->buffers->handle
+				 + buf->offset + start);
+			data[dwords++] = RADEON_CP_PACKET2;
+		}
+
+		buf_priv->dispatched = 1;
+
+		/* Fire off the indirect buffer */
+		BEGIN_RING( 3 );
+
+		OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) );
+		OUT_RING( offset );
+		OUT_RING( dwords );
+
+		ADVANCE_RING();
+	}
+
+	if ( buf_priv->discard ) {
+		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+		/* Emit the indirect buffer age */
+		BEGIN_RING( 2 );
+		RADEON_DISPATCH_AGE( buf_priv->age );
+		ADVANCE_RING();
+
+		buf->pending = 1;
+		buf->used = 0;
+		/* FIXME: Check dispatched field */
+		buf_priv->dispatched = 0;
+	}
+
+	dev_priv->sarea_priv->last_dispatch++;
+}
+
+static void radeon_cp_dispatch_indices( drm_device_t *dev,
+					drm_buf_t *buf,
+					int start, int end,
+					int count )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int format = sarea_priv->vc_format;
+	int offset = dev_priv->agp_buffers_offset;
+	int prim = buf_priv->prim;
+	u32 *data;
+	int dwords;
+	int i = 0;
+	RING_LOCALS;
+	DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
+
+	radeon_update_ring_snapshot( dev_priv );
+
+	if ( 0 )
+		radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
+
+	if ( start != end ) {
+		buf_priv->dispatched = 1;
+
+		if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+			radeon_emit_state( dev_priv );
+		}
+
+		dwords = (end - start + 3) / sizeof(u32);
+
+		data = (u32 *)((char *)dev_priv->buffers->handle
+			       + buf->offset + start);
+
+		data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
+
+		data[1] = offset;
+		data[2] = RADEON_MAX_VB_VERTS;
+		data[3] = format;
+		data[4] = (prim | RADEON_PRIM_WALK_IND |
+			   RADEON_COLOR_ORDER_RGBA |
+			   RADEON_VTX_FMT_RADEON_MODE |
+			   (count << RADEON_NUM_VERTICES_SHIFT) );
+
+		if ( count & 0x1 ) {
+			data[dwords-1] &= 0x0000ffff;
+		}
+
+		do {
+			/* Emit the next set of up to three cliprects */
+			if ( i < sarea_priv->nbox ) {
+				radeon_emit_clip_rect( dev_priv,
+						       &sarea_priv->boxes[i] );
+			}
+
+			radeon_cp_dispatch_indirect( dev, buf, start, end );
+
+			i++;
+		} while ( i < sarea_priv->nbox );
+	}
+
+	if ( buf_priv->discard ) {
+		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+		/* Emit the vertex buffer age */
+		BEGIN_RING( 2 );
+		RADEON_DISPATCH_AGE( buf_priv->age );
+		ADVANCE_RING();
+
+		buf->pending = 1;
+		/* FIXME: Check dispatched field */
+		buf_priv->dispatched = 0;
+	}
+
+	dev_priv->sarea_priv->last_dispatch++;
+
+	sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
+	sarea_priv->nbox = 0;
+}
+
+static int radeon_cp_dispatch_blit( drm_device_t *dev,
+				    drm_radeon_blit_t *blit )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_radeon_buf_priv_t *buf_priv;
+	u32 format;
+	u32 *data;
+	int dword_shift, dwords;
+	RING_LOCALS;
+	DRM_DEBUG( "blit: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
+		   blit->offset >> 10, blit->pitch, blit->format,
+		   blit->x, blit->y, blit->width, blit->height );
+
+	radeon_update_ring_snapshot( dev_priv );
+
+	/* The compiler won't optimize away a division by a variable,
+	 * even if the only legal values are powers of two.  Thus, we'll
+	 * use a shift instead.
+	 */
+	switch ( blit->format ) {
+	case RADEON_TXF_32BPP_ARGB8888:
+	case RADEON_TXF_32BPP_RGBA8888:
+		format = RADEON_COLOR_FORMAT_ARGB8888;
+		dword_shift = 0;
+		break;
+	case RADEON_TXF_16BPP_AI88:
+	case RADEON_TXF_16BPP_ARGB1555:
+	case RADEON_TXF_16BPP_RGB565:
+	case RADEON_TXF_16BPP_ARGB4444:
+		format = RADEON_COLOR_FORMAT_RGB565;
+		dword_shift = 1;
+		break;
+	case RADEON_TXF_8BPP_I:
+	case RADEON_TXF_8BPP_RGB332:
+		format = RADEON_COLOR_FORMAT_CI8;
+		dword_shift = 2;
+		break;
+	default:
+		DRM_ERROR( "invalid blit format %d\n", blit->format );
+		return -EINVAL;
+	}
+
+	/* Flush the pixel cache.  This ensures no pixel data gets mixed
+	 * up with the texture data from the host data blit, otherwise
+	 * part of the texture image may be corrupted.
+	 */
+	BEGIN_RING( 4 );
+
+	RADEON_FLUSH_CACHE();
+	RADEON_WAIT_UNTIL_IDLE();
+
+	ADVANCE_RING();
+
+	/* Dispatch the indirect buffer.
+	 */
+	buf = dma->buflist[blit->idx];
+	buf_priv = buf->dev_private;
+
+	if ( buf->pid != current->pid ) {
+		DRM_ERROR( "process %d using buffer owned by %d\n",
+			   current->pid, buf->pid );
+		return -EINVAL;
+	}
+	if ( buf->pending ) {
+		DRM_ERROR( "sending pending buffer %d\n", blit->idx );
+		return -EINVAL;
+	}
+
+	buf_priv->discard = 1;
+
+	dwords = (blit->width * blit->height) >> dword_shift;
+	if ( !dwords ) dwords = 1;
+
+	data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
+
+	data[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
+	data[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+		   RADEON_GMC_BRUSH_NONE |
+		   (format << 8) |
+		   RADEON_GMC_SRC_DATATYPE_COLOR |
+		   RADEON_ROP3_S |
+		   RADEON_DP_SRC_SOURCE_HOST_DATA |
+		   RADEON_GMC_CLR_CMP_CNTL_DIS |
+		   RADEON_GMC_WR_MSK_DIS);
+
+	data[2] = (blit->pitch << 22) | (blit->offset >> 10);
+	data[3] = 0xffffffff;
+	data[4] = 0xffffffff;
+	data[5] = (blit->y << 16) | blit->x;
+	data[6] = (blit->height << 16) | blit->width;
+	data[7] = dwords;
+
+	buf->used = (dwords + 8) * sizeof(u32);
+
+	radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
+
+	/* Flush the pixel cache after the blit completes.  This ensures
+	 * the texture data is written out to memory before rendering
+	 * continues.
+	 */
+	BEGIN_RING( 4 );
+
+	RADEON_FLUSH_CACHE();
+	RADEON_WAIT_UNTIL_2D_IDLE();
+
+	ADVANCE_RING();
+
+	return 0;
+}
+
+static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	radeon_update_ring_snapshot( dev_priv );
+
+	BEGIN_RING( 35 );
+
+	OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
+	OUT_RING( 0x00000000 );
+
+	OUT_RING( CP_PACKET0_TABLE( RADEON_RE_STIPPLE_DATA, 31 ) );
+	for ( i = 0 ; i < 32 ; i++ ) {
+		OUT_RING( stipple[i] );
+	}
+
+	ADVANCE_RING();
+}
+
+
+/* ================================================================
+ * IOCTL functions
+ */
+
+int radeon_cp_clear( struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_clear_t clear;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if ( copy_from_user( &clear, (drm_radeon_clear_t *) arg,
+			     sizeof(clear) ) )
+		return -EFAULT;
+
+	if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
+		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+	radeon_cp_dispatch_clear( dev, &clear );
+
+	return 0;
+}
+
+int radeon_cp_swap( struct inode *inode, struct file *filp,
+		    unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
+		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+	if ( !dev_priv->page_flipping ) {
+		radeon_cp_dispatch_swap( dev );
+		dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
+						RADEON_UPLOAD_MASKS);
+	} else {
+		radeon_cp_dispatch_flip( dev );
+	}
+
+	return 0;
+}
+
+int radeon_cp_vertex( struct inode *inode, struct file *filp,
+		      unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_radeon_buf_priv_t *buf_priv;
+	drm_radeon_vertex_t vertex;
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+	if ( !dev_priv || dev_priv->is_pci ) {
+		DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if ( copy_from_user( &vertex, (drm_radeon_vertex_t *)arg,
+			     sizeof(vertex) ) )
+		return -EFAULT;
+
+	DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n",
+		   __FUNCTION__, current->pid,
+		   vertex.idx, vertex.count, vertex.discard );
+
+	if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
+		DRM_ERROR( "buffer index %d (of %d max)\n",
+			   vertex.idx, dma->buf_count - 1 );
+		return -EINVAL;
+	}
+	if ( vertex.prim < 0 ||
+	     vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+		DRM_ERROR( "buffer prim %d\n", vertex.prim );
+		return -EINVAL;
+	}
+
+	VB_AGE_CHECK_WITH_RET( dev_priv );
+
+	buf = dma->buflist[vertex.idx];
+	buf_priv = buf->dev_private;
+
+	if ( buf->pid != current->pid ) {
+		DRM_ERROR( "process %d using buffer owned by %d\n",
+			   current->pid, buf->pid );
+		return -EINVAL;
+	}
+	if ( buf->pending ) {
+		DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
+		return -EINVAL;
+	}
+
+	buf->used = vertex.count;
+	buf_priv->prim = vertex.prim;
+	buf_priv->discard = vertex.discard;
+
+	radeon_cp_dispatch_vertex( dev, buf );
+
+	return 0;
+}
+
+int radeon_cp_indices( struct inode *inode, struct file *filp,
+		       unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_radeon_buf_priv_t *buf_priv;
+	drm_radeon_indices_t elts;
+	int count;
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+	if ( !dev_priv || dev_priv->is_pci ) {
+		DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if ( copy_from_user( &elts, (drm_radeon_indices_t *)arg,
+			     sizeof(elts) ) )
+		return -EFAULT;
+
+	DRM_DEBUG( "%s: pid=%d index=%d start=%d end=%d discard=%d\n",
+		   __FUNCTION__, current->pid,
+		   elts.idx, elts.start, elts.end, elts.discard );
+
+	if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
+		DRM_ERROR( "buffer index %d (of %d max)\n",
+			   elts.idx, dma->buf_count - 1 );
+		return -EINVAL;
+	}
+	if ( elts.prim < 0 ||
+	     elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+		DRM_ERROR( "buffer prim %d\n", elts.prim );
+		return -EINVAL;
+	}
+
+	VB_AGE_CHECK_WITH_RET( dev_priv );
+
+	buf = dma->buflist[elts.idx];
+	buf_priv = buf->dev_private;
+
+	if ( buf->pid != current->pid ) {
+		DRM_ERROR( "process %d using buffer owned by %d\n",
+			   current->pid, buf->pid );
+		return -EINVAL;
+	}
+	if ( buf->pending ) {
+		DRM_ERROR( "sending pending buffer %d\n", elts.idx );
+		return -EINVAL;
+	}
+
+	count = (elts.end - elts.start) / sizeof(u16);
+	elts.start -= RADEON_INDEX_PRIM_OFFSET;
+
+	if ( elts.start & 0x7 ) {
+		DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
+		return -EINVAL;
+	}
+	if ( elts.start < buf->used ) {
+		DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
+		return -EINVAL;
+	}
+
+	buf->used = elts.end;
+	buf_priv->prim = elts.prim;
+	buf_priv->discard = elts.discard;
+
+	radeon_cp_dispatch_indices( dev, buf, elts.start, elts.end, count );
+
+	return 0;
+}
+
+int radeon_cp_blit( struct inode *inode, struct file *filp,
+		    unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_radeon_blit_t blit;
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if ( copy_from_user( &blit, (drm_radeon_blit_t *)arg,
+			     sizeof(blit) ) )
+		return -EFAULT;
+
+	DRM_DEBUG( "%s: pid=%d index=%d\n",
+		   __FUNCTION__, current->pid, blit.idx );
+
+	if ( blit.idx < 0 || blit.idx > dma->buf_count ) {
+		DRM_ERROR( "sending %d buffers (of %d max)\n",
+			   blit.idx, dma->buf_count );
+		return -EINVAL;
+	}
+
+	VB_AGE_CHECK_WITH_RET( dev_priv );
+
+	return radeon_cp_dispatch_blit( dev, &blit );
+}
+
+int radeon_cp_stipple( struct inode *inode, struct file *filp,
+		       unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_radeon_stipple_t stipple;
+	u32 mask[32];
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg,
+			     sizeof(stipple) ) )
+		return -EFAULT;
+
+	if ( copy_from_user( &mask, stipple.mask,
+			     32 * sizeof(u32) ) )
+		return -EFAULT;
+
+	radeon_cp_dispatch_stipple( dev, mask );
+
+	return 0;
+}
+
+int radeon_cp_indirect( struct inode *inode, struct file *filp,
+			unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_radeon_buf_priv_t *buf_priv;
+	drm_radeon_indirect_t indirect;
+	RING_LOCALS;
+
+	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
+	     dev->lock.pid != current->pid ) {
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+	if ( !dev_priv || dev_priv->is_pci ) {
+		DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if ( copy_from_user( &indirect, (drm_radeon_indirect_t *)arg,
+			     sizeof(indirect) ) )
+		return -EFAULT;
+
+	DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
+		   indirect.idx, indirect.start,
+		   indirect.end, indirect.discard );
+
+	if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
+		DRM_ERROR( "buffer index %d (of %d max)\n",
+			   indirect.idx, dma->buf_count - 1 );
+		return -EINVAL;
+	}
+
+	buf = dma->buflist[indirect.idx];
+	buf_priv = buf->dev_private;
+
+	if ( buf->pid != current->pid ) {
+		DRM_ERROR( "process %d using buffer owned by %d\n",
+			   current->pid, buf->pid );
+		return -EINVAL;
+	}
+	if ( buf->pending ) {
+		DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
+		return -EINVAL;
+	}
+
+	if ( indirect.start < buf->used ) {
+		DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
+			   indirect.start, buf->used );
+		return -EINVAL;
+	}
+
+	VB_AGE_CHECK_WITH_RET( dev_priv );
+
+	buf->used = indirect.end;
+	buf_priv->discard = indirect.discard;
+
+	/* Wait for the 3D stream to idle before the indirect buffer
+	 * containing 2D acceleration commands is processed.
+	 */
+	BEGIN_RING( 2 );
+
+	RADEON_WAIT_UNTIL_3D_IDLE();
+
+	ADVANCE_RING();
+
+	/* Dispatch the indirect buffer full of commands from the
+	 * X server.  This is insecure and is thus only available to
+	 * privileged clients.
+	 */
+	radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.0/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.4.0/linux/drivers/char/misc.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/misc.c	Mon Jan 22 13:30:20 2001
@@ -70,7 +70,6 @@
 extern void gfx_register(void);
 #endif
 extern void streamable_init(void);
-extern int rtc_sun_init(void);		/* Combines MK48T02 and MK48T08 */
 extern int rtc_DP8570A_init(void);
 extern int rtc_MK48T08_init(void);
 extern int ds1286_init(void);
@@ -258,9 +257,6 @@
 #endif
 #ifdef CONFIG_BVME6000
 	rtc_DP8570A_init();
-#endif
-#if defined(CONFIG_SUN_MOSTEK_RTC)
-	rtc_sun_init();
 #endif
 #ifdef CONFIG_SGI_DS1286
 	ds1286_init();
diff -u --recursive --new-file v2.4.0/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.4.0/linux/drivers/char/n_tty.c	Mon Jul 31 10:14:07 2000
+++ linux/drivers/char/n_tty.c	Mon Jan 15 18:58:04 2001
@@ -86,6 +86,15 @@
 		free_page((unsigned long) buf);
 }
 
+static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+{
+	if (tty->read_cnt < N_TTY_BUF_SIZE) {
+		tty->read_buf[tty->read_head] = c;
+		tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
+		tty->read_cnt++;
+	}
+}
+
 static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
 {
 	unsigned long flags;
@@ -94,11 +103,7 @@
 	 *	Why didn't anyone see this one comming? --AJK
 	*/
 	spin_lock_irqsave(&tty->read_lock, flags);
-	if (tty->read_cnt < N_TTY_BUF_SIZE) {
-		tty->read_buf[tty->read_head] = c;
-		tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
-		tty->read_cnt++;
-	}
+	put_tty_queue_nolock(c, tty);
 	spin_unlock_irqrestore(&tty->read_lock, flags);
 }
 
@@ -499,6 +504,8 @@
 
 static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 {
+	unsigned long flags;
+
 	if (tty->raw) {
 		put_tty_queue(c, tty);
 		return;
@@ -651,10 +658,12 @@
 				put_tty_queue(c, tty);
 
 		handle_newline:
+			spin_lock_irqsave(&tty->read_lock, flags);
 			set_bit(tty->read_head, &tty->read_flags);
-			put_tty_queue(c, tty);
+			put_tty_queue_nolock(c, tty);
 			tty->canon_head = tty->read_head;
 			tty->canon_data++;
+			spin_unlock_irqrestore(&tty->read_lock, flags);
 			kill_fasync(&tty->fasync, SIGIO, POLL_IN);
 			if (waitqueue_active(&tty->read_wait))
 				wake_up_interruptible(&tty->read_wait);
@@ -1055,12 +1064,6 @@
 				tty->read_tail = ((tty->read_tail+1) &
 						  (N_TTY_BUF_SIZE-1));
 				tty->read_cnt--;
-				spin_unlock_irqrestore(&tty->read_lock, flags);
-
-				if (!eol || (c != __DISABLED_CHAR)) {
-					put_user(c, b++);
-					nr--;
-				}
 				if (eol) {
 					/* this test should be redundant:
 					 * we shouldn't be reading data if
@@ -1068,8 +1071,15 @@
 					 */
 					if (--tty->canon_data < 0)
 						tty->canon_data = 0;
-					break;
 				}
+				spin_unlock_irqrestore(&tty->read_lock, flags);
+
+				if (!eol || (c != __DISABLED_CHAR)) {
+					put_user(c, b++);
+					nr--;
+				}
+				if (eol)
+					break;
 			}
 		} else {
 			int uncopied;
diff -u --recursive --new-file v2.4.0/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c
--- v2.4.0/linux/drivers/i2o/i2o_block.c	Wed Nov  8 17:09:50 2000
+++ linux/drivers/i2o/i2o_block.c	Sun Jan 28 13:37:18 2001
@@ -392,7 +392,6 @@
 
 	if (req->nr_segments < max_segments) {
 		req->nr_segments++;
-		q->elevator.nr_segments++;
 		return 1;
 	}
 	return 0;
@@ -421,22 +420,16 @@
 {
 	int max_segments = i2ob_dev[MINOR(req->rq_dev)].max_segments;
 	int total_segments = req->nr_segments + next->nr_segments;
-	int same_segment;
 
 	if (__max_segments < max_segments)
 		max_segments = __max_segments;
 
-	same_segment = 0;
 	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data)
-	{
 		total_segments--;
-		same_segment = 1;
-	}
     
 	if (total_segments > max_segments)
 		return 0;
 
-	q->elevator.nr_segments -= same_segment;
 	req->nr_segments = total_segments;
 	return 1;
 }
diff -u --recursive --new-file v2.4.0/linux/drivers/ide/hpt366.c linux/drivers/ide/hpt366.c
--- v2.4.0/linux/drivers/ide/hpt366.c	Tue Jan  2 16:58:45 2001
+++ linux/drivers/ide/hpt366.c	Sat Jan 27 08:45:58 2001
@@ -55,6 +55,15 @@
 };
 
 const char *bad_ata66_4[] = {
+	"IBM-DTLA-307075",
+	"IBM-DTLA-307060",
+	"IBM-DTLA-307045",
+	"IBM-DTLA-307030",
+	"IBM-DTLA-307020",
+	"IBM-DTLA-307015",
+	"IBM-DTLA-305040",
+	"IBM-DTLA-305030",
+	"IBM-DTLA-305020",
 	"WDC AC310200R",
 	NULL
 };
diff -u --recursive --new-file v2.4.0/linux/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- v2.4.0/linux/drivers/ide/ide-cd.c	Tue Jan  2 16:59:17 2001
+++ linux/drivers/ide/ide-cd.c	Sun Jan 28 13:37:50 2001
@@ -288,6 +288,9 @@
  * 4.59  Aug 11, 2000	- Fix changer problem in cdrom_read_toc, we weren't
  *			  correctly sensing a disc change.
  *			- Rearranged some code
+ *			- Use extended sense on drives that support it for
+ *			  correctly reporting tray status -- from
+ *			  Michael D Johnson <johnsom@orst.edu>
  *
  *************************************************************************/
  
@@ -759,16 +762,13 @@
  * changed 5 parameters to 3 for dvd-ram
  * struct packet_command *pc; now packet_command_t *pc;
  */
-#undef CLASSIC_PACKET_STRUCT
 static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
 					  struct packet_command *pc,
 					  ide_handler_t *handler)
 {
-#ifdef CLASSIC_PACKET_STRUCT
 	unsigned char *cmd_buf	= pc->c;
 	int cmd_len		= sizeof(pc->c);
 	unsigned int timeout	= pc->timeout;
-#endif
 	ide_startstop_t startstop;
 
 	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
@@ -786,22 +786,10 @@
 	}
 
 	/* Arm the interrupt handler. */
-#ifdef CLASSIC_PACKET_STRUCT
-	/* Arm the interrupt handler. */
 	ide_set_handler (drive, handler, timeout, cdrom_timer_expiry);
 
 	/* Send the command to the device. */
 	atapi_output_bytes (drive, cmd_buf, cmd_len);
-#else /* !CLASSIC_PACKET_STRUCT */
-	/* Arm the interrupt handler. */
-//	ide_set_handler (drive, handler, (unsigned int) pc->timeout, cdrom_timer_expiry);
-	ide_set_handler (drive, handler, pc->timeout, cdrom_timer_expiry);
-
-	/* Send the command to the device. */
-//	atapi_output_bytes (drive, (void *)pc->c, (unsigned int) sizeof(pc->c));
-	atapi_output_bytes (drive, pc->c, sizeof(pc->c));
-#endif /* CLASSIC_PACKET_STRUCT */
-
 	return ide_started;
 }
 
@@ -1884,9 +1872,6 @@
 	   If it is, just return. */
 	(void) cdrom_check_status(drive, sense);
 
-	if (CDROM_STATE_FLAGS(drive)->toc_valid)
-		return 0;
-
 	/* First read just the header, so we know how long the TOC is. */
 	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
 				    sizeof(struct atapi_toc_header), sense);
@@ -2324,11 +2309,17 @@
 		    sense.ascq == 0x04)
 			return CDS_DISC_OK;
 
+
+		/*
+		 * If not using Mt Fuji extended media tray reports,
+		 * just return TRAY_OPEN since ATAPI doesn't provide
+		 * any other way to detect this...
+		 */
 		if (sense.sense_key == NOT_READY) {
-			/* ATAPI doesn't have anything that can help
-			   us decide whether the drive is really
-			   emtpy or the tray is just open. irk. */
-			return CDS_TRAY_OPEN;
+			if (sense.asc == 0x3a && (!sense.ascq||sense.ascq == 1))
+				return CDS_NO_DISC;
+			else
+				return CDS_TRAY_OPEN;
 		}
 
 		return CDS_DRIVE_NOT_READY;
@@ -2597,7 +2588,7 @@
 	if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram)
         	printk (" DVD%s%s", 
         	(CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "", 
-        	(CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "AM" : "");
+        	(CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "-RAM" : "");
 
         if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw) 
         	printk (" CD%s%s", 
diff -u --recursive --new-file v2.4.0/linux/drivers/ide/ide-dma.c linux/drivers/ide/ide-dma.c
--- v2.4.0/linux/drivers/ide/ide-dma.c	Tue Jan  2 16:58:45 2001
+++ linux/drivers/ide/ide-dma.c	Mon Jan 15 13:08:15 2001
@@ -226,6 +226,9 @@
 		unsigned char *virt_addr = bh->b_data;
 		unsigned int size = bh->b_size;
 
+		if (nents >= PRD_ENTRIES)
+			return 0;
+
 		while ((bh = bh->b_reqnext) != NULL) {
 			if ((virt_addr + size) != (unsigned char *) bh->b_data)
 				break;
@@ -259,6 +262,9 @@
 
 	HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
 
+	if (!i)
+		return 0;
+
 	sg = HWIF(drive)->sg_table;
 	while (i && sg_dma_len(sg)) {
 		u32 cur_addr;
@@ -274,7 +280,7 @@
 		 */
 
 		while (cur_len) {
-			if (++count >= PRD_ENTRIES) {
+			if (count++ >= PRD_ENTRIES) {
 				printk("%s: DMA table too small\n", drive->name);
 				pci_unmap_sg(HWIF(drive)->pci_dev,
 					     HWIF(drive)->sg_table,
diff -u --recursive --new-file v2.4.0/linux/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c
--- v2.4.0/linux/drivers/ide/ide-probe.c	Thu Oct 26 23:35:48 2000
+++ linux/drivers/ide/ide-probe.c	Mon Jan 15 13:08:15 2001
@@ -134,7 +134,7 @@
 					break;
 				}
 #endif
-				printk ("CDROM");
+				printk ("CD/DVD-ROM");
 				break;
 			case ide_tape:
 				printk ("TAPE");
@@ -761,9 +761,10 @@
 	for (unit = 0; unit < minors; ++unit) {
 		*bs++ = BLOCK_SIZE;
 #ifdef CONFIG_BLK_DEV_PDC4030
-		*max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : MAX_SECTORS);
+		*max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : 256);
 #else
-		*max_sect++ = MAX_SECTORS;
+		/* IDE can do up to 128K per request. */
+		*max_sect++ = 256;
 #endif
 		*max_ra++ = MAX_READAHEAD;
 	}
diff -u --recursive --new-file v2.4.0/linux/drivers/ide/via82cxxx.c linux/drivers/ide/via82cxxx.c
--- v2.4.0/linux/drivers/ide/via82cxxx.c	Tue Nov  7 11:02:24 2000
+++ linux/drivers/ide/via82cxxx.c	Wed Jan 24 09:12:56 2001
@@ -602,7 +602,9 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
 		hwif->dmaproc = &via82cxxx_dmaproc;
+#ifdef CONFIG_IDEDMA_AUTO
 		hwif->autodma = 1;
+#endif
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 }
diff -u --recursive --new-file v2.4.0/linux/drivers/isdn/hisax/Makefile linux/drivers/isdn/hisax/Makefile
--- v2.4.0/linux/drivers/isdn/hisax/Makefile	Fri Dec 29 14:40:54 2000
+++ linux/drivers/isdn/hisax/Makefile	Mon Jan  8 15:06:01 2001
@@ -34,8 +34,8 @@
 hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o
 hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o
 hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o
-hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hfc_2bs0.o
-hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hfc_2bs0.o
+hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o
+hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o
 hisax-objs-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o
 hisax-objs-$(CONFIG_HISAX_NETJET_U) += nj_u.o netjet.o icc.o
 hisax-objs-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o
diff -u --recursive --new-file v2.4.0/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- v2.4.0/linux/drivers/isdn/hisax/config.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/isdn/hisax/config.c	Mon Jan 29 12:24:07 2001
@@ -1708,8 +1708,8 @@
 }
 
 static struct pci_device_id hisax_pci_tbl[] __initdata = {
-#ifdef CONFIG_HISAX_FRTIZPCI
-	{PCI_VENDOR_ID_AVM,      PCI_DEVICE_ID_AVM_FRITZ,        PCI_ANY_ID, PCI_ANY_ID},
+#ifdef CONFIG_HISAX_FRITZPCI
+	{PCI_VENDOR_ID_AVM,      PCI_DEVICE_ID_AVM_A1,          PCI_ANY_ID, PCI_ANY_ID},
 #endif
 #ifdef CONFIG_HISAX_DIEHLDIVA
 	{PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA20,     PCI_ANY_ID, PCI_ANY_ID},
diff -u --recursive --new-file v2.4.0/linux/drivers/isdn/hisax/isdnl3.c linux/drivers/isdn/hisax/isdnl3.c
--- v2.4.0/linux/drivers/isdn/hisax/isdnl3.c	Tue Nov 28 21:43:13 2000
+++ linux/drivers/isdn/hisax/isdnl3.c	Mon Jan  8 15:19:34 2001
@@ -566,7 +566,7 @@
 			} else {
 				struct sk_buff *skb = arg;
 
-				skb_queue_head(&st->l3.squeue, skb);
+				skb_queue_tail(&st->l3.squeue, skb);
 				FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); 
 			}
 			break;
diff -u --recursive --new-file v2.4.0/linux/drivers/isdn/hisax/md5sums.asc linux/drivers/isdn/hisax/md5sums.asc
--- v2.4.0/linux/drivers/isdn/hisax/md5sums.asc	Thu Jan  4 13:20:17 2001
+++ linux/drivers/isdn/hisax/md5sums.asc	Wed Jan 10 14:12:53 2001
@@ -10,7 +10,7 @@
 ca7bd9bac39203f3074f3f093948cc3c  isac.c
 a2ad619fd404b3149099a2984de9d23c  isdnl1.c
 d2a78e407f3d94876deac160c6f9aae6  isdnl2.c
-a109841c2e75b11fc8ef2c8718e24c3e  isdnl3.c
+e7932ca7ae39c497c17f13a2e1434fcd  isdnl3.c
 afb5f2f4ac296d6de45c856993b161e1  tei.c
 00023e2a482cb86a26ea870577ade5d6  callc.c
 a1834e9b2ec068440cff2e899eff4710  cert.c
@@ -25,9 +25,9 @@
 Version: 2.6.3i
 Charset: noconv
 
-iQCVAwUBOlMTgDpxHvX/mS9tAQFSbgP/W9y6tnnWHTRLGqyr3EY1OHZiQXERkAAu
-hp+Y8PIoX1GgAh4yZ7xhYwUsk6y0z5USdGuhC9ZHh+oZd57lPsJMnhkEZR5BVsYT
-r7jHwelP527+QCLkVUCHIVIWUW0ANzeZBhDV2vefkFb+gWLiZsBhaHssbcKGsMNG
-Ak4xS1ByqsM=
-=lsIJ
+iQCVAwUBOlxeLTpxHvX/mS9tAQH6RwP8DhyvqAnXFV6WIGi16iQ3vKikkPoqnDQs
+GEn5uCW0dPYKlwthD2Grj/JbMYZhOmCFuDxF7ufJnjTSDe/D8XNe2wngxzAiwcIe
+WjCrT8X95cuP3HZHscbFTEinVV0GAnoI0ZEgs5eBDhVHDqILLYMaTFBQaRH3jgXc
+i5VH88jPfUM=
+=qc+J
 -----END PGP SIGNATURE-----
diff -u --recursive --new-file v2.4.0/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.4.0/linux/drivers/isdn/isdn_common.c	Tue Jan  2 16:45:38 2001
+++ linux/drivers/isdn/isdn_common.c	Mon Jan  8 15:06:01 2001
@@ -1512,7 +1512,7 @@
 					int i;
 
 					if ((ret = verify_area(VERIFY_READ, (void *) arg,
-					(ISDN_MODEM_NUMREG + ISDN_MSNLEN)
+					(ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
 						   * ISDN_MAX_CHANNELS)))
 						return ret;
 
@@ -1521,6 +1521,9 @@
 						     ISDN_MODEM_NUMREG))
 							return -EFAULT;
 						p += ISDN_MODEM_NUMREG;
+						if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
+							return -EFAULT;
+						p += ISDN_LMSNLEN;
 						if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
 							return -EFAULT;
 						p += ISDN_MSNLEN;
diff -u --recursive --new-file v2.4.0/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.4.0/linux/drivers/isdn/isdn_net.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/isdn/isdn_net.c	Mon Jan  8 15:06:01 2001
@@ -2325,6 +2325,7 @@
 	memset(netdev, 0, sizeof(isdn_net_dev));
 	if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) {
 		printk(KERN_WARNING "isdn_net: Could not allocate device locals\n");
+		kfree(netdev);
 		return NULL;
 	}
 	memset(netdev->local, 0, sizeof(isdn_net_local));
diff -u --recursive --new-file v2.4.0/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.4.0/linux/drivers/isdn/isdn_ppp.c	Tue Nov 28 21:43:13 2000
+++ linux/drivers/isdn/isdn_ppp.c	Mon Jan 22 12:21:54 2001
@@ -1131,9 +1131,9 @@
 			proto = PPP_IPX;	/* untested */
 			break;
 		default:
-			dev_kfree_skb(skb);
 			printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n", 
 			       skb->protocol);
+			dev_kfree_skb(skb);
 			return 0;
 	}
 
@@ -2310,8 +2310,7 @@
   		rsparm.data = rsdata;
   		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
   
-		/* !!!HACK,HACK,HACK!!! 2048 is only assumed */
-  		skb_out = dev_alloc_skb(2048);
+  		skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
 		len = ipc->decompress(stat, skb, skb_out, &rsparm);
 		kfree_skb(skb);
 		if (len <= 0) {
@@ -2332,14 +2331,9 @@
 			kfree_skb(skb_out);
 			return NULL;
 		}
-
-		if (isdn_ppp_skip_ac(ri, skb) < 0) {
-			kfree_skb(skb);
-			return NULL;
-		}
-		*proto = isdn_ppp_strip_proto(skb);
+		*proto = isdn_ppp_strip_proto(skb_out);
 		if (*proto < 0) {
-			kfree_skb(skb);
+			kfree_skb(skb_out);
 			return NULL;
 		}
 		return skb_out;
diff -u --recursive --new-file v2.4.0/linux/drivers/isdn/isdn_v110.c linux/drivers/isdn/isdn_v110.c
--- v2.4.0/linux/drivers/isdn/isdn_v110.c	Sun Aug  6 12:43:42 2000
+++ linux/drivers/isdn/isdn_v110.c	Mon Jan 15 15:31:18 2001
@@ -102,7 +102,7 @@
 	int i;
 	isdn_v110_stream *v;
 
-	if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_KERNEL)) == NULL)
+	if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
 		return NULL;
 	memset(v, 0, sizeof(isdn_v110_stream));
 	v->key = key;
@@ -134,7 +134,7 @@
 	v->b = 0;
 	v->skbres = hdrlen;
 	v->maxsize = maxsize - hdrlen;
-	if ((v->encodebuf = kmalloc(maxsize, GFP_KERNEL)) == NULL) {
+	if ((v->encodebuf = kmalloc(maxsize, GFP_ATOMIC)) == NULL) {
 		kfree(v);
 		return NULL;
 	}
diff -u --recursive --new-file v2.4.0/linux/drivers/md/Config.in linux/drivers/md/Config.in
--- v2.4.0/linux/drivers/md/Config.in	Mon Oct  2 12:00:07 2000
+++ linux/drivers/md/Config.in	Mon Jan 29 13:16:00 2001
@@ -11,12 +11,7 @@
 dep_tristate '  RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD
 dep_tristate '  RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD
 dep_tristate '  RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD
-if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_RAID0" = "y" -o "$CONFIG_MD_RAID1" = "y" -o "$CONFIG_MD_RAID5" = "y" ]; then
-        bool '  Boot support' CONFIG_MD_BOOT
-        bool '  Auto Detect support' CONFIG_AUTODETECT_RAID
-fi
 
 dep_tristate ' Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM $CONFIG_MD
-dep_mbool '   LVM information in proc filesystem' CONFIG_LVM_PROC_FS $CONFIG_BLK_DEV_LVM
 
 endmenu
diff -u --recursive --new-file v2.4.0/linux/drivers/md/lvm-snap.c linux/drivers/md/lvm-snap.c
--- v2.4.0/linux/drivers/md/lvm-snap.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/md/lvm-snap.c	Sun Jan 28 16:11:20 2001
@@ -21,6 +21,14 @@
  *
  */
 
+/*
+ * Changelog
+ *
+ *    05/07/2000 - implemented persistent snapshot support
+ *    23/11/2000 - used cpu_to_le64 rather than my own macro
+ *
+ */
+
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <linux/blkdev.h>
@@ -30,7 +38,9 @@
 #include <linux/lvm.h>
 
 
-static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.9 snapshot code (13/11/2000)\n";
+#include "lvm-snap.h"
+
+static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.9.1_beta2 snapshot code (18/01/2001)\n";
 
 extern const char *const lvm_name;
 extern int lvm_blocksizes[];
@@ -214,10 +224,10 @@
 	memset(lv_COW_table, 0, blksize_snap);
 	for ( ; is < lv_snap->lv_remap_ptr; is++, id++) {
 		/* store new COW_table entry */
-		lv_COW_table[id].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org));
-		lv_COW_table[id].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_org);
-		lv_COW_table[id].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new));
-		lv_COW_table[id].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_new);
+		lv_COW_table[id].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org));
+		lv_COW_table[id].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_org);
+		lv_COW_table[id].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new));
+		lv_COW_table[id].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_new);
 	}
 }
 
@@ -227,8 +237,7 @@
  *
  */
 
-int lvm_write_COW_table_block(vg_t * vg,
-			      lv_t * lv_snap)
+int lvm_write_COW_table_block(vg_t * vg, lv_t * lv_snap)
 {
 	int blksize_snap;
 	int end_of_table;
@@ -268,10 +277,10 @@
 	blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10);
 
 	/* store new COW_table entry */
-	lv_COW_table[idx_COW_table].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org));
-	lv_COW_table[idx_COW_table].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_org);
-	lv_COW_table[idx_COW_table].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, snap_phys_dev));
-	lv_COW_table[idx_COW_table].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_new);
+	lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org));
+	lv_COW_table[idx_COW_table].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_org);
+	lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, snap_phys_dev));
+	lv_COW_table[idx_COW_table].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_new);
 
 	length_tmp = iobuf->length;
 	iobuf->length = blksize_snap;
@@ -568,6 +577,7 @@
 	}
 	if (lv->lv_iobuf)
 	{
+	        kiobuf_wait_for_io(lv->lv_iobuf);
 		unmap_kiobuf(lv->lv_iobuf);
 		free_kiovec(1, &lv->lv_iobuf);
 		lv->lv_iobuf = NULL;
diff -u --recursive --new-file v2.4.0/linux/drivers/md/lvm-snap.h linux/drivers/md/lvm-snap.h
--- v2.4.0/linux/drivers/md/lvm-snap.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/md/lvm-snap.h	Sun Jan 28 16:11:20 2001
@@ -0,0 +1,47 @@
+/*
+ * kernel/lvm-snap.h
+ *
+ * Copyright (C) 2001 Sistina Software
+ *
+ *
+ * LVM driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * LVM driver 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 GNU CC; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+ * Changelog
+ *
+ *    05/01/2001:Joe Thornber - Factored this file out of lvm.c
+ *
+ */
+
+#ifndef LVM_SNAP_H
+#define LVM_SNAP_H
+
+/* external snapshot calls */
+extern inline int lvm_get_blksize(kdev_t);
+extern int lvm_snapshot_alloc(lv_t *);
+extern void lvm_snapshot_fill_COW_page(vg_t *, lv_t *);
+extern int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *);
+extern int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *);
+extern void lvm_snapshot_release(lv_t *); 
+extern int lvm_write_COW_table_block(vg_t *, lv_t *);
+extern inline void lvm_hash_link(lv_block_exception_t *, 
+				 kdev_t, ulong, lv_t *);
+extern int lvm_snapshot_alloc_hash_table(lv_t *);
+extern void lvm_drop_snapshot(lv_t *, const char *);
+
+#endif
diff -u --recursive --new-file v2.4.0/linux/drivers/md/lvm.c linux/drivers/md/lvm.c
--- v2.4.0/linux/drivers/md/lvm.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/md/lvm.c	Sun Jan 28 16:11:20 2001
@@ -7,22 +7,23 @@
  * April-May,July-August,November 1998
  * January-March,May,July,September,October 1999
  * January,February,July,September-November 2000
+ * January 2001
  *
  *
  * LVM driver is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
  * any later version.
- * 
+ *
  * LVM driver 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 GNU CC; see the file COPYING.  If not, write to
  * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA. 
+ * Boston, MA 02111-1307, USA.
  *
  */
 
@@ -138,13 +139,21 @@
  *    01/11/2000 - added memory information on hash tables to
  *                 lvm_proc_get_global_info()
  *    02/11/2000 - implemented /proc/lvm/ hierarchy
- *    07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown
+ *    22/11/2000 - changed lvm_do_create_proc_entry_of_pv () to work
+ *                 with devfs
+ *    26/11/2000 - corrected #ifdef locations for PROC_FS
+ *    28/11/2000 - fixed lvm_do_vg_extend() NULL pointer BUG
+ *               - fixed lvm_do_create_proc_entry_of_pv() buffer tampering BUG
+ *    08/01/2001 - Removed conditional compiles related to PROC_FS,
+ *                 procfs is always supported now. (JT)
+ *    12/01/2001 - avoided flushing logical volume in case of shrinking
+ *                 because of unecessary overhead in case of heavy updates
  *
  */
 
 
-static char *lvm_version = "LVM version 0.9  by Heinz Mauelshagen  (13/11/2000)\n";
-static char *lvm_short_version = "version 0.9 (13/11/2000)";
+static char *lvm_version = "LVM version 0.9.1_beta2  by Heinz Mauelshagen  (18/01/2001)\n";
+static char *lvm_short_version = "version 0.9.1_beta2 (18/01/2001)";
 
 #define MAJOR_NR	LVM_BLK_MAJOR
 #define	DEVICE_OFF(device)
@@ -190,6 +199,8 @@
 #include <linux/errno.h>
 #include <linux/lvm.h>
 
+#include "lvm-snap.h"
+
 #define	LVM_CORRECT_READ_AHEAD( a) \
    if      ( a < LVM_MIN_READ_AHEAD || \
              a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD;
@@ -198,19 +209,28 @@
 #  define WRITEA WRITE
 #endif
 
-/*
- * External function prototypes
- */
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
+/* debug macros */
+#ifdef DEBUG_IOCTL
+#define P_IOCTL(fmt, args...) printk(KERN_DEBUG "lvm ioctl: " fmt, ## args)
 #else
-extern int lvm_init(void);
+#define P_IOCTL(fmt, args...)
 #endif
 
-static void lvm_dummy_device_request(request_queue_t *);
-#define	DEVICE_REQUEST	lvm_dummy_device_request
+#ifdef DEBUG_MAP
+#define P_MAP(fmt, args...) printk(KERN_DEBUG "lvm map: " fmt, ## args)
+#else
+#define P_MAP(fmt, args...)
+#endif
+
+#ifdef DEBUG_KFREE
+#define P_KFREE(fmt, args...) printk(KERN_DEBUG "lvm kfree: " fmt, ## args)
+#else
+#define P_KFREE(fmt, args...)
+#endif
 
+/*
+ * External function prototypes
+ */
 static int lvm_make_request_fn(request_queue_t*, int, struct buffer_head*);
 
 static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong);
@@ -224,42 +244,29 @@
 
 static int lvm_chr_ioctl(struct inode *, struct file *, uint, ulong);
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 int lvm_proc_read_vg_info(char *, char **, off_t, int, int *, void *);
 int lvm_proc_read_lv_info(char *, char **, off_t, int, int *, void *);
 int lvm_proc_read_pv_info(char *, char **, off_t, int, int *, void *);
 static int lvm_proc_get_global_info(char *, char **, off_t, int, int *, void *);
+
+void lvm_do_create_devfs_entry_of_vg ( vg_t *);
+
 void lvm_do_create_proc_entry_of_vg ( vg_t *);
-inline void lvm_do_remove_proc_entry_of_vg ( vg_t *);
-inline void lvm_do_create_proc_entry_of_lv ( vg_t *, lv_t *);
-inline void lvm_do_remove_proc_entry_of_lv ( vg_t *, lv_t *);
-inline void lvm_do_create_proc_entry_of_pv ( vg_t *, pv_t *);
-inline void lvm_do_remove_proc_entry_of_pv ( vg_t *, pv_t *);
-#endif
+void lvm_do_remove_proc_entry_of_vg ( vg_t *);
+void lvm_do_create_proc_entry_of_lv ( vg_t *, lv_t *);
+void lvm_do_remove_proc_entry_of_lv ( vg_t *, lv_t *);
+void lvm_do_create_proc_entry_of_pv ( vg_t *, pv_t *);
+void lvm_do_remove_proc_entry_of_pv ( vg_t *, pv_t *);
 
-#ifdef LVM_HD_NAME
-void lvm_hd_name(char *, int);
-#endif
 /* End external function prototypes */
 
 
 /*
  * Internal function prototypes
  */
+static void lvm_cleanup(void);
 static void lvm_init_vars(void);
 
-/* external snapshot calls */
-extern inline int lvm_get_blksize(kdev_t);
-extern int lvm_snapshot_alloc(lv_t *);
-extern void lvm_snapshot_fill_COW_page(vg_t *, lv_t *);
-extern int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *);
-extern int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *);
-extern void lvm_snapshot_release(lv_t *); 
-extern int lvm_write_COW_table_block(vg_t *, lv_t *);
-extern inline void lvm_hash_link(lv_block_exception_t *, kdev_t, ulong, lv_t *);
-extern int lvm_snapshot_alloc_hash_table(lv_t *);
-extern void lvm_drop_snapshot(lv_t *, char *);
-
 #ifdef LVM_HD_NAME
 extern void (*lvm_hd_name_ptr) (char *, int);
 #endif
@@ -288,9 +295,9 @@
 static int lvm_do_vg_rename(vg_t *, void *);
 static int lvm_do_vg_remove(int);
 static void lvm_geninit(struct gendisk *);
-#ifdef LVM_GET_INODE
-static struct inode *lvm_get_inode(int);
-void lvm_clear_inode(struct inode *);
+static char *lvm_show_uuid ( char *);
+#ifdef LVM_HD_NAME
+void lvm_hd_name(char *, int);
 #endif
 /* END Internal function prototypes */
 
@@ -298,12 +305,10 @@
 /* volume group descriptor area pointers */
 static vg_t *vg[ABS_MAX_VG];
 
-#ifdef	CONFIG_DEVFS_FS
 static devfs_handle_t lvm_devfs_handle;
 static devfs_handle_t vg_devfs_handle[MAX_VG];
 static devfs_handle_t ch_devfs_handle[MAX_VG];
 static devfs_handle_t lv_devfs_handle[MAX_LV];
-#endif
 
 static pv_t *pvp = NULL;
 static lv_t *lvp = NULL;
@@ -340,18 +345,15 @@
 static uint vg_count = 0;
 static long lvm_chr_open_count = 0;
 static ushort lvm_iop_version = LVM_DRIVER_IOP_VERSION;
-static DECLARE_WAIT_QUEUE_HEAD(lvm_snapshot_wait);
 static DECLARE_WAIT_QUEUE_HEAD(lvm_wait);
 static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait);
 
 static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 static struct proc_dir_entry *lvm_proc_dir = NULL;
 static struct proc_dir_entry *lvm_proc_vg_subdir = NULL;
 struct proc_dir_entry *pde = NULL;
-#endif
 
 static struct file_operations lvm_chr_fops =
 {
@@ -360,7 +362,7 @@
 	ioctl:		lvm_chr_ioctl,
 };
 
-#define BLOCK_DEVICE_OPERATIONS
+
 /* block device operations structure needed for 2.3.38? and above */
 static struct block_device_operations lvm_blk_dops =
 {
@@ -391,22 +393,10 @@
 	NULL,			/* pointer to next gendisk struct (internal) */
 };
 
-
-#ifdef MODULE
-/*
- * Module initialization...
- */
-int init_module(void)
-#else
 /*
  * Driver initialization...
  */
-#ifdef __initfunc
-__initfunc(int lvm_init(void))
-#else
-int __init lvm_init(void)
-#endif
-#endif				/* #ifdef MODULE */
+int lvm_init(void)
 {
 	struct gendisk *gendisk_ptr = NULL;
 
@@ -414,11 +404,7 @@
 		printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name);
 		return -EIO;
 	}
-#ifdef BLOCK_DEVICE_OPERATIONS
 	if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
-#else
-	if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_fops) < 0)
-#endif
 	{
 		printk("%s -- register_blkdev failed\n", lvm_name);
 		if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
@@ -426,21 +412,17 @@
 		return -EIO;
 	}
 
-#ifdef	CONFIG_DEVFS_FS
 	lvm_devfs_handle = devfs_register(
 		0 , "lvm", 0, 0, LVM_CHAR_MAJOR,
 		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
 		&lvm_chr_fops, NULL);
-#endif
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 	lvm_proc_dir = create_proc_entry (LVM_DIR, S_IFDIR, &proc_root);
 	if (lvm_proc_dir != NULL) {
 		lvm_proc_vg_subdir = create_proc_entry (LVM_VG_SUBDIR, S_IFDIR, lvm_proc_dir);
 		pde = create_proc_entry(LVM_GLOBAL, S_IFREG, lvm_proc_dir);
 		if ( pde != NULL) pde->read_proc = &lvm_proc_get_global_info;
 	}
-#endif
 
 	lvm_init_vars();
 	lvm_geninit(&lvm_gendisk);
@@ -464,9 +446,9 @@
 	lvm_hd_name_ptr = lvm_hd_name;
 #endif
 
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
 	blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn);
 
+
 	/* optional read root VGDA */
 /*
    if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
@@ -483,20 +465,17 @@
 	       lvm_version, lvm_name);
 
 	return 0;
-} /* init_module() / lvm_init() */
+} /* lvm_init() */
 
 
-#ifdef MODULE
 /*
- * Module cleanup...
+ * cleanup...
  */
-void cleanup_module(void)
+static void lvm_cleanup(void)
 {
 	struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL;
 
-#ifdef	CONFIG_DEVFS_FS
 	devfs_unregister (lvm_devfs_handle);
-#endif
 
 	if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) {
 		printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);
@@ -504,7 +483,7 @@
 	if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) {
 		printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name);
 	}
-	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+
 
 	gendisk_ptr = gendisk_ptr_prev = gendisk_head;
 	while (gendisk_ptr != NULL) {
@@ -521,11 +500,9 @@
 	blksize_size[MAJOR_NR] = NULL;
 	hardsect_size[MAJOR_NR] = NULL;
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 	remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
 	remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
 	remove_proc_entry(LVM_DIR, &proc_root);
-#endif
 
 #ifdef LVM_HD_NAME
 	/* reference from linux/drivers/block/genhd.c */
@@ -535,18 +512,13 @@
 	printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name);
 
 	return;
-}	/* void cleanup_module() */
-#endif	/* #ifdef MODULE */
+}	/* lvm_cleanup() */
 
 
 /*
  * support function to initialize lvm variables
  */
-#ifdef __initfunc
-__initfunc(void lvm_init_vars(void))
-#else
 void __init lvm_init_vars(void)
-#endif
 {
 	int v;
 
@@ -626,13 +598,9 @@
 	/* otherwise cc will complain about unused variables */
 	(void) lvm_lock;
 
-
-#ifdef DEBUG_IOCTL
-	printk(KERN_DEBUG
-	       "%s -- lvm_chr_ioctl: command: 0x%X  MINOR: %d  "
-	       "VG#: %d  mode: 0x%X\n",
-	       lvm_name, command, minor, VG_CHR(minor), file->f_mode);
-#endif
+	P_IOCTL("%s -- lvm_chr_ioctl: command: 0x%X  MINOR: %d  "
+		"VG#: %d  mode: 0x%X\n",
+		lvm_name, command, minor, VG_CHR(minor), file->f_mode);
 
 #ifdef LVM_TOTAL_RESET
 	if (lvm_reset_spindown > 0) return -EACCES;
@@ -890,14 +858,12 @@
 		if (lv_ptr->lv_status & LV_SPINDOWN) return -EPERM;
 
 		/* Check inactive LV and open for read/write */
-		if (file->f_mode & O_RDWR) {
-			if (!(lv_ptr->lv_status & LV_ACTIVE)) return -EPERM;
-			if (!(lv_ptr->lv_access & LV_WRITE))  return -EACCES;
-		}
+		if (!(lv_ptr->lv_status & LV_ACTIVE))
+			return -EPERM;
+		if (!(lv_ptr->lv_access & LV_WRITE) &&
+		    (file->f_mode & FMODE_WRITE))
+			return -EACCES;
 
-#ifndef BLOCK_DEVICE_OPERATIONS
-		file->f_op = &lvm_blk_fops;
-#endif
 
                 /* be sure to increment VG counter */
 		if (lv_ptr->lv_open == 0) vg_ptr->lv_open++;
@@ -930,24 +896,18 @@
 	void *arg = (void *) a;
 	struct hd_geometry *hd = (struct hd_geometry *) a;
 
-#ifdef DEBUG_IOCTL
-	printk(KERN_DEBUG
-	       "%s -- lvm_blk_ioctl MINOR: %d  command: 0x%X  arg: %X  "
-	       "VG#: %dl  LV#: %d\n",
-	       lvm_name, minor, command, (ulong) arg,
-	       VG_BLK(minor), LV_BLK(minor));
-#endif
+	P_IOCTL("%s -- lvm_blk_ioctl MINOR: %d  command: 0x%X  arg: %X  "
+		"VG#: %dl  LV#: %d\n",
+		lvm_name, minor, command, (ulong) arg,
+		VG_BLK(minor), LV_BLK(minor));
 
 	switch (command) {
 	case BLKGETSIZE:
 		/* return device size */
-#ifdef DEBUG_IOCTL
-		printk(KERN_DEBUG
-		       "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
-		       lvm_name, lv_ptr->lv_size);
-#endif
+		P_IOCTL("%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",
+			lvm_name, lv_ptr->lv_size);
 		if (put_user(lv_ptr->lv_size, (long *)arg))
-			return -EFAULT; 
+			return -EFAULT;
 		break;
 
 
@@ -955,10 +915,8 @@
 		/* flush buffer cache */
 		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 
-#ifdef DEBUG_IOCTL
-		printk(KERN_DEBUG
-		       "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name);
-#endif
+		P_IOCTL("%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name);
+
 		fsync_dev(inode->i_rdev);
 		invalidate_buffers(inode->i_rdev);
 		break;
@@ -968,11 +926,9 @@
 		/* set read ahead for block device */
 		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 
-#ifdef DEBUG_IOCTL
-		printk(KERN_DEBUG
-		       "%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n",
-		       lvm_name, (long) arg, MAJOR(inode->i_rdev), minor);
-#endif
+		P_IOCTL("%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n",
+			lvm_name, (long) arg, MAJOR(inode->i_rdev), minor);
+
 		if ((long) arg < LVM_MIN_READ_AHEAD ||
 		    (long) arg > LVM_MAX_READ_AHEAD)
 			return -EINVAL;
@@ -982,10 +938,7 @@
 
 	case BLKRAGET:
 		/* get current read ahead setting */
-#ifdef DEBUG_IOCTL
-		printk(KERN_DEBUG
-		       "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name);
-#endif
+		P_IOCTL("%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name);
 		if (put_user(lv_ptr->lv_read_ahead, (long *)arg))
 			return -EFAULT;
 		break;
@@ -993,10 +946,7 @@
 
 	case HDIO_GETGEO:
 		/* get disk geometry */
-#ifdef DEBUG_IOCTL
-		printk(KERN_DEBUG
-		       "%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name);
-#endif
+		P_IOCTL("%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name);
 		if (hd == NULL)
 			return -EINVAL;
 		{
@@ -1016,11 +966,8 @@
 				return -EFAULT;
 		}
 
-#ifdef DEBUG_IOCTL
-		printk(KERN_DEBUG
-		       "%s -- lvm_blk_ioctl -- cylinders: %d\n",
-		       lvm_name, lv_ptr->lv_size / heads / sectors);
-#endif
+		P_IOCTL("%s -- lvm_blk_ioctl -- cylinders: %d\n",
+			lvm_name, lv_ptr->lv_size / heads / sectors);
 		break;
 
 
@@ -1127,22 +1074,22 @@
 	struct buffer_head bh;
 	unsigned long block;
 	int err;
-	
+
 	if (get_user(block, &user_result->lv_block))
-	return -EFAULT;
-	
+		return -EFAULT;
+
 	memset(&bh,0,sizeof bh);
 	bh.b_rsector = block;
 	bh.b_dev = bh.b_rdev = inode->i_dev;
 	bh.b_size = lvm_get_blksize(bh.b_dev);
 	if ((err=lvm_map(&bh, READ)) < 0)  {
-	printk("lvm map failed: %d\n", err);
-	return -EINVAL;
+		printk("lvm map failed: %d\n", err);
+		return -EINVAL;
 	}
-	
-	return put_user(  kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) ||
+
+	return put_user(kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) ||
 	put_user(bh.b_rsector, &user_result->lv_block) ? -EFAULT : 0;
-}     
+}
 
 
 /*
@@ -1168,7 +1115,7 @@
 		     vg_ptr->pe_total,
 		     vg_ptr->pe_allocated * vg_ptr->pe_size >> 1,
 	     	     vg_ptr->pe_allocated,
-		     (vg_ptr->pe_total - vg_ptr->pe_allocated) *	
+		     (vg_ptr->pe_total - vg_ptr->pe_allocated) *
 	     	     vg_ptr->pe_size >> 1,
 		     vg_ptr->pe_total - vg_ptr->pe_allocated);
 	return sz;
@@ -1263,7 +1210,6 @@
 }
 
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 /*
  * Support functions /proc-Filesystem
  */
@@ -1325,10 +1271,7 @@
 		lv_block_exception_t_bytes *= sizeof(lv_block_exception_t);
 
 		if (buf != NULL) {
-#ifdef DEBUG_KFREE
-			printk(KERN_DEBUG
-			       "%s -- vfree %d\n", lvm_name, __LINE__);
-#endif
+			P_KFREE("%s -- vfree %d\n", lvm_name, __LINE__);
 			lock_kernel();
 			vfree(buf);
 			unlock_kernel();
@@ -1452,7 +1395,6 @@
 	else
 		return count;
 } /* lvm_proc_get_global_info() */
-#endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */
 
 
 /*
@@ -1478,7 +1420,7 @@
 	sz += sprintf ( page+sz, "PE size:      %u\n", vg->pe_size / 2);
 	sz += sprintf ( page+sz, "PE total:     %u\n", vg->pe_total);
 	sz += sprintf ( page+sz, "PE allocated: %u\n", vg->pe_allocated);
-	sz += sprintf ( page+sz, "uuid:         %s\n", vg->vg_uuid);
+	sz += sprintf ( page+sz, "uuid:         %s\n", lvm_show_uuid(vg->vg_uuid));
 
 	return sz;
 }
@@ -1525,7 +1467,7 @@
 	sz += sprintf ( page+sz, "PE allocated: %u\n", pv->pe_allocated);
 	sz += sprintf ( page+sz, "device:       %02u:%02u\n",
                         MAJOR(pv->pv_dev), MINOR(pv->pv_dev));
-	sz += sprintf ( page+sz, "uuid:         %s\n", pv->pv_uuid);
+	sz += sprintf ( page+sz, "uuid:         %s\n", lvm_show_uuid(pv->pv_uuid));
 
 
 	return sz;
@@ -1565,15 +1507,13 @@
 		       lvm_name, lv->lv_name);
 		return -1;
 	}
-#ifdef DEBUG_MAP
-	printk(KERN_DEBUG
-	       "%s - lvm_map minor:%d  *rdev: %02d:%02d  *rsector: %lu  "
-	       "size:%lu\n",
-	       lvm_name, minor,
-	       MAJOR(rdev_tmp),
-	       MINOR(rdev_tmp),
-	       rsector_tmp, size);
-#endif
+
+	P_MAP("%s - lvm_map minor:%d  *rdev: %02d:%02d  *rsector: %lu  "
+	      "size:%lu\n",
+	      lvm_name, minor,
+	      MAJOR(rdev_tmp),
+	      MINOR(rdev_tmp),
+	      rsector_tmp, size);
 
 	if (rsector_tmp + size > lv->lv_size) {
 		printk(KERN_ALERT
@@ -1595,15 +1535,13 @@
 		    (rsector_tmp % vg_this->pe_size);
 		rdev_tmp = lv->lv_current_pe[index].dev;
 
-#ifdef DEBUG_MAP
-		printk(KERN_DEBUG
-		       "lv_current_pe[%ld].pe: %ld  rdev: %02d:%02d  rsector:%ld\n",
+		P_MAP("lv_current_pe[%ld].pe: %ld  rdev: %02d:%02d  "
+		      "rsector:%ld\n",
 		       index,
 		       lv->lv_current_pe[index].pe,
 		       MAJOR(rdev_tmp),
 		       MINOR(rdev_tmp),
 		       rsector_tmp);
-#endif
 
 		/* striped mapping */
 	} else {
@@ -1624,9 +1562,7 @@
 		rdev_tmp = lv->lv_current_pe[index].dev;
 	}
 
-#ifdef DEBUG_MAP
-	printk(KERN_DEBUG
-	     "lv_current_pe[%ld].pe: %ld  rdev: %02d:%02d  rsector:%ld\n"
+	P_MAP("lv_current_pe[%ld].pe: %ld  rdev: %02d:%02d  rsector:%ld\n"
 	       "stripe_length: %ld  stripe_index: %ld\n",
 	       index,
 	       lv->lv_current_pe[index].pe,
@@ -1635,7 +1571,6 @@
 	       rsector_tmp,
 	       stripe_length,
 	       stripe_index);
-#endif
 
 	/* handle physical extents on the move */
 	if (pe_lock_req.lock == LOCK_PE) {
@@ -1659,6 +1594,8 @@
 	if (lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)) {
 		/* original logical volume */
 		if (lv->lv_access & LV_SNAPSHOT_ORG) {
+			/* Serializes the access to the lv_snapshot_next list */
+			down(&lv->lv_snapshot_sem);
 			if (rw == WRITE || rw == WRITEA)
 			{
 				lv_t *lv_ptr;
@@ -1669,7 +1606,8 @@
 				     lv_ptr = lv_ptr->lv_snapshot_next) {
 					/* Check for inactive snapshot */
 					if (!(lv_ptr->lv_status & LV_ACTIVE)) continue;
-					down(&lv->lv_snapshot_org->lv_snapshot_sem);
+					/* Serializes the COW with the accesses to the snapshot device */
+					down(&lv_ptr->lv_snapshot_sem);
 					/* do we still have exception storage for this snapshot free? */
 					if (lv_ptr->lv_block_exception != NULL) {
 						rdev_sav = rdev_tmp;
@@ -1690,9 +1628,10 @@
 						rdev_tmp = rdev_sav;
 						rsector_tmp = rsector_sav;
 					}
-					up(&lv->lv_snapshot_org->lv_snapshot_sem);
+					up(&lv_ptr->lv_snapshot_sem);
 				}
 			}
+			up(&lv->lv_snapshot_sem);
 		} else {
 			/* remap snapshot logical volume */
 			down(&lv->lv_snapshot_sem);
@@ -1733,31 +1672,12 @@
 
 
 /*
- * this one never should be called...
- */
-static void lvm_dummy_device_request(request_queue_t * t)
-{
-	printk(KERN_EMERG
-	     "%s -- oops, got lvm request for %02d:%02d [sector: %lu]\n",
-	       lvm_name,
-	       MAJOR(CURRENT->rq_dev),
-	       MINOR(CURRENT->rq_dev),
-	       CURRENT->sector);
-	return;
-}
-
-
-/*
  * make request function
  */
 static int lvm_make_request_fn(request_queue_t *q,
 			       int rw,
-			       struct buffer_head *bh)
-{
-	if (lvm_map(bh, rw)<0)
-		return 0; /* failure, buffer_IO_error has been called, don't recurse */
-	else
-		return 1; /* all ok, mapping done, call lower level driver */
+			       struct buffer_head *bh) {
+	return (lvm_map(bh, rw) < 0) ? 0 : 1;
 }
 
 
@@ -1774,10 +1694,8 @@
 lock_try_again:
 	spin_lock(&lvm_lock);
 	if (lock != 0 && lock != current->pid) {
-#ifdef DEBUG_IOCTL
-		printk(KERN_INFO "lvm_do_lock_lvm: %s is locked by pid %d ...\n",
-		       lvm_name, lock);
-#endif
+		P_IOCTL("lvm_do_lock_lvm: %s is locked by pid %d ...\n",
+			lvm_name, lock);
 		spin_unlock(&lvm_lock);
 		interruptible_sleep_on(&lvm_wait);
 		if (current->sigpending != 0)
@@ -1966,6 +1884,8 @@
 		}
 	}
 
+	lvm_do_create_devfs_entry_of_vg ( vg_ptr);
+
 	/* Second path to correct snapshot logical volumes which are not
 	   in place during first path above */
 	for (l = 0; l < ls; l++) {
@@ -1980,18 +1900,7 @@
 		}
 	}
 
-#ifdef	CONFIG_DEVFS_FS
-	vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL);
-	ch_devfs_handle[vg_ptr->vg_number] = devfs_register(
-		vg_devfs_handle[vg_ptr->vg_number] , "group",
-		DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number,
-		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
-		&lvm_chr_fops, NULL);
-#endif
-
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 	lvm_do_create_proc_entry_of_vg ( vg_ptr);
-#endif
 
 	vfree(snap_lv_ptr);
 
@@ -2021,25 +1930,15 @@
 		for (p = 0; p < vg_ptr->pv_max; p++) {
 			if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) {
 				ret = lvm_do_pv_create(arg, vg_ptr, p);
-				lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);
 				if ( ret != 0) return ret;
-	
-				/* We don't need the PE list
-				   in kernel space like LVs pe_t list */
-				pv_ptr->pe = NULL;
-				vg_ptr->pv_cur++;
-				vg_ptr->pv_act++;
-				vg_ptr->pe_total +=
-				    pv_ptr->pe_total;
-#ifdef LVM_GET_INODE
-				/* insert a dummy inode for fs_may_mount */
-				pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);
-#endif
+				pv_ptr = vg_ptr->pv[p];
+				vg_ptr->pe_total += pv_ptr->pe_total;
+				lvm_do_create_proc_entry_of_pv(vg_ptr, pv_ptr);
 				return 0;
 			}
 		}
 	}
-return -EPERM;
+	return -EPERM;
 } /* lvm_do_vg_extend() */
 
 
@@ -2060,10 +1959,6 @@
 		    strcmp(pv_ptr->pv_name,
 			       pv_name) == 0) {
 			if (pv_ptr->lv_cur > 0) return -EPERM;
-			vg_ptr->pe_total -=
-			    pv_ptr->pe_total;
-			vg_ptr->pv_cur--;
-			vg_ptr->pv_act--;
 			lvm_do_pv_remove(vg_ptr, p);
 			/* Make PV pointer array contiguous */
 			for (; p < vg_ptr->pv_max - 1; p++)
@@ -2091,9 +1986,7 @@
 	if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0)
 		return -EFAULT;
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 	lvm_do_remove_proc_entry_of_vg ( vg_ptr);
-#endif
 
 	strncpy ( vg_ptr->vg_name, vg_name, sizeof ( vg_name)-1);
 	for ( l = 0; l < vg_ptr->lv_max; l++)
@@ -2115,9 +2008,7 @@
 		strncpy(pv_ptr->vg_name, vg_name, NAME_LEN);
 	}
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 	lvm_do_create_proc_entry_of_vg ( vg_ptr);
-#endif
 
 	return 0;
 } /* lvm_do_vg_rename */
@@ -2166,27 +2057,17 @@
 	/* free PVs */
 	for (i = 0; i < vg_ptr->pv_max; i++) {
 		if ((pv_ptr = vg_ptr->pv[i]) != NULL) {
-#ifdef DEBUG_KFREE
-			printk(KERN_DEBUG
-			       "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
+			P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
 			lvm_do_pv_remove(vg_ptr, i);
 		}
 	}
 
-#ifdef	CONFIG_DEVFS_FS
 	devfs_unregister (ch_devfs_handle[vg_ptr->vg_number]);
 	devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]);
-#endif
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 	lvm_do_remove_proc_entry_of_vg ( vg_ptr);
-#endif
-
-#ifdef DEBUG_KFREE
-	printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
 
+	P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
 	kfree(vg_ptr);
 	vg[VG_CHR(minor)] = NULL;
 
@@ -2222,11 +2103,6 @@
 	vg_ptr->pv_act++;
 	vg_ptr->pv_cur++;
 
-#ifdef LVM_GET_INODE
-	/* insert a dummy inode for fs_may_mount */
-	pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);
-#endif
-
 	return 0;
 } /* lvm_do_pv_create() */
 
@@ -2237,11 +2113,8 @@
 static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) {
 	pv_t *pv_ptr = vg_ptr->pv[p];
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 	lvm_do_remove_proc_entry_of_pv ( vg_ptr, pv_ptr);
-#endif
-	vg_ptr->pe_total -=
-	    pv_ptr->pe_total;
+	vg_ptr->pe_total -= pv_ptr->pe_total;
 	vg_ptr->pv_cur--;
 	vg_ptr->pv_act--;
 #ifdef LVM_GET_INODE
@@ -2320,11 +2193,9 @@
 			       "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "
 			       "at line %d\n",
 			       lvm_name, size, __LINE__);
-#ifdef DEBUG_KFREE
-			printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
+			P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
 			kfree(lv_ptr);
-			vg[VG_CHR(minor)]->lv[l] = NULL;
+			vg_ptr->lv[l] = NULL;
 			return -ENOMEM;
 		}
 		if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) {
@@ -2354,9 +2225,8 @@
 					       "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "
 					       "of %d byte at line %d\n",
 					       lvm_name, size, __LINE__);
-#ifdef DEBUG_KFREE
-					printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
+					P_KFREE("%s -- kfree %d\n", lvm_name,
+						__LINE__);
 					kfree(lv_ptr);
 					vg_ptr->lv[l] = NULL;
 					return -ENOMEM;
@@ -2364,7 +2234,7 @@
 				if (copy_from_user(lv_ptr->lv_block_exception, lvbe, size)) {
 					vfree(lv_ptr->lv_block_exception);
 					kfree(lv_ptr);
-					vg[VG_CHR(minor)]->lv[l] = NULL;
+					vg_ptr->lv[l] = NULL;
 					return -EFAULT;
 				}
 				/* point to the original logical volume */
@@ -2372,33 +2242,32 @@
 
 				lv_ptr->lv_snapshot_minor = 0;
 				lv_ptr->lv_snapshot_org = lv_ptr;
-				lv_ptr->lv_snapshot_prev = NULL;
-				/* walk thrugh the snapshot list */
-				while (lv_ptr->lv_snapshot_next != NULL)
-					lv_ptr = lv_ptr->lv_snapshot_next;
-				/* now lv_ptr points to the last existing snapshot in the chain */
-				vg_ptr->lv[l]->lv_snapshot_prev = lv_ptr;
 				/* our new one now back points to the previous last in the chain
 				   which can be the original logical volume */
 				lv_ptr = vg_ptr->lv[l];
 				/* now lv_ptr points to our new last snapshot logical volume */
-				lv_ptr->lv_snapshot_org = lv_ptr->lv_snapshot_prev->lv_snapshot_org;
-				lv_ptr->lv_snapshot_next = NULL;
 				lv_ptr->lv_current_pe = lv_ptr->lv_snapshot_org->lv_current_pe;
+				lv_ptr->lv_allocated_snapshot_le = lv_ptr->lv_allocated_le;
 				lv_ptr->lv_allocated_le = lv_ptr->lv_snapshot_org->lv_allocated_le;
 				lv_ptr->lv_current_le = lv_ptr->lv_snapshot_org->lv_current_le;
 				lv_ptr->lv_size = lv_ptr->lv_snapshot_org->lv_size;
 				lv_ptr->lv_stripes = lv_ptr->lv_snapshot_org->lv_stripes;
 				lv_ptr->lv_stripesize = lv_ptr->lv_snapshot_org->lv_stripesize;
+
+				/* Update the VG PE(s) used by snapshot reserve space. */
+				vg_ptr->pe_allocated += lv_ptr->lv_allocated_snapshot_le;
+
 				if ((ret = lvm_snapshot_alloc(lv_ptr)) != 0)
 				{
 					vfree(lv_ptr->lv_block_exception);
 					kfree(lv_ptr);
-					vg[VG_CHR(minor)]->lv[l] = NULL;
+					vg_ptr->lv[l] = NULL;
 					return ret;
 				}
 				for ( e = 0; e < lv_ptr->lv_remap_ptr; e++)
-					lvm_hash_link (lv_ptr->lv_block_exception + e, lv_ptr->lv_block_exception[e].rdev_org, lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
+					lvm_hash_link (lv_ptr->lv_block_exception + e,
+						       lv_ptr->lv_block_exception[e].rdev_org,
+						       lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
 				/* need to fill the COW exception table data
 				   into the page for disk i/o */
 				lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr);
@@ -2426,9 +2295,8 @@
 	vg_ptr->lv_cur++;
 	lv_ptr->lv_status = lv_status_save;
 
-#ifdef	CONFIG_DEVFS_FS
 	{
-	char *lv_tmp, *lv_buf = NULL;
+	char *lv_tmp, *lv_buf = lv->lv_name;
 
 	strtok(lv->lv_name, "/");       /* /dev */
 	while((lv_tmp = strtok(NULL, "/")) != NULL)
@@ -2440,24 +2308,29 @@
 		S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
 		&lvm_blk_dops, NULL);
 	}
-#endif
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 	lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
-#endif
 
 	/* optionally add our new snapshot LV */
 	if (lv_ptr->lv_access & LV_SNAPSHOT) {
+		lv_t *org = lv_ptr->lv_snapshot_org, *last;
+
 		/* sync the original logical volume */
-		fsync_dev(lv_ptr->lv_snapshot_org->lv_dev);
+		fsync_dev(org->lv_dev);
 #ifdef	LVM_VFS_ENHANCEMENT
 		/* VFS function call to sync and lock the filesystem */
-		fsync_dev_lockfs(lv_ptr->lv_snapshot_org->lv_dev);
+		fsync_dev_lockfs(org->lv_dev);
 #endif
-		lv_ptr->lv_snapshot_org->lv_access |= LV_SNAPSHOT_ORG;
-		lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG;
-		/* put ourselve into the chain */
-		lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr;
+
+		down(&org->lv_snapshot_sem);
+		org->lv_access |= LV_SNAPSHOT_ORG;
+		lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */
+
+		/* Link in the list of snapshot volumes */
+		for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next);
+		lv_ptr->lv_snapshot_prev = last;
+		last->lv_snapshot_next = lv_ptr;
+		up(&org->lv_snapshot_sem);
 	}
 
 	/* activate the logical volume */
@@ -2513,6 +2386,31 @@
 	    lv_ptr->lv_snapshot_next != NULL)
 		return -EPERM;
 
+	if (lv_ptr->lv_access & LV_SNAPSHOT) {
+		/*
+		 * Atomically make the the snapshot invisible
+		 * to the original lv before playing with it.
+		 */
+		lv_t * org = lv_ptr->lv_snapshot_org;
+		down(&org->lv_snapshot_sem);
+
+		/* remove this snapshot logical volume from the chain */
+		lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next;
+		if (lv_ptr->lv_snapshot_next != NULL) {
+			lv_ptr->lv_snapshot_next->lv_snapshot_prev =
+			    lv_ptr->lv_snapshot_prev;
+		}
+		up(&org->lv_snapshot_sem);
+
+		/* no more snapshots? */
+		if (!org->lv_snapshot_next)
+			org->lv_access &= ~LV_SNAPSHOT_ORG;
+		lvm_snapshot_release(lv_ptr);
+
+		/* Update the VG PE(s) used by snapshot reserve space. */
+		vg_ptr->pe_allocated -= lv_ptr->lv_allocated_snapshot_le;
+	}
+
 	lv_ptr->lv_status |= LV_SPINDOWN;
 
 	/* sync the buffers */
@@ -2532,7 +2430,8 @@
 	vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = ABS_MAX_VG;
 	vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = -1;
 
-	/* correct the PE count in PVs if this is no snapshot logical volume */
+	/* correct the PE count in PVs if this is not a snapshot
+           logical volume */
 	if (!(lv_ptr->lv_access & LV_SNAPSHOT)) {
 		/* only if this is no snapshot logical volume because
 		   we share the lv_current_pe[] structs with the
@@ -2546,31 +2445,13 @@
 			}
 		}
 		vfree(lv_ptr->lv_current_pe);
-	/* LV_SNAPSHOT */
-	} else {
-		/* remove this snapshot logical volume from the chain */
-		lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next;
-		if (lv_ptr->lv_snapshot_next != NULL) {
-			lv_ptr->lv_snapshot_next->lv_snapshot_prev =
-			    lv_ptr->lv_snapshot_prev;
-		}
-		/* no more snapshots? */
-		if (lv_ptr->lv_snapshot_org->lv_snapshot_next == NULL)
-			lv_ptr->lv_snapshot_org->lv_access &= ~LV_SNAPSHOT_ORG;
-		lvm_snapshot_release(lv_ptr);
 	}
 
-#ifdef	CONFIG_DEVFS_FS
 	devfs_unregister(lv_devfs_handle[lv_ptr->lv_number]);
-#endif
 
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 	lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
-#endif
 
-#ifdef DEBUG_KFREE
-	printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);
-#endif
+	P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
 	kfree(lv_ptr);
 	vg_ptr->lv[l] = NULL;
 	vg_ptr->lv_cur--;
@@ -2638,21 +2519,24 @@
 		}
 		memcpy(lvbe,
 		       lv_ptr->lv_block_exception,
-		       (lv->lv_remap_end > lv_ptr->lv_remap_end ? lv_ptr->lv_remap_ptr : lv->lv_remap_end) * sizeof(lv_block_exception_t));
+		       (lv->lv_remap_end > lv_ptr->lv_remap_end ?
+			lv_ptr->lv_remap_ptr : lv->lv_remap_end) * sizeof(lv_block_exception_t));
 
 		lv_ptr->lv_block_exception = lvbe;
 		lv_ptr->lv_remap_end = lv->lv_remap_end;
 		if (lvm_snapshot_alloc_hash_table(lv_ptr) != 0)
 		{
-			lvm_drop_snapshot(lv_ptr, "hash_alloc");
+			lvm_drop_snapshot(lv_ptr, "no memory for hash table");
 			up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
 			vfree(lvbe_old);
 			vfree(lvs_hash_table_old);
-			return 1;
+			return -ENOMEM;
 		}
 
 		for (e = 0; e < lv_ptr->lv_remap_ptr; e++)
-			lvm_hash_link (lv_ptr->lv_block_exception + e, lv_ptr->lv_block_exception[e].rdev_org, lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
+			lvm_hash_link (lv_ptr->lv_block_exception + e,
+				       lv_ptr->lv_block_exception[e].rdev_org,
+				       lv_ptr->lv_block_exception[e].rsector_org, lv_ptr);
 
 		up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem);
 
@@ -2677,15 +2561,6 @@
 		return -EFAULT;
 	}
 
-#ifdef DEBUG
-	printk(KERN_DEBUG
-	       "%s -- fsync_dev and "
-	       "invalidate_buffers for %s [%s] in %s\n",
-	       lvm_name, lv_ptr->lv_name,
-	       kdevname(lv_ptr->lv_dev),
-	       vg_ptr->vg_name);
-#endif
-
 	/* reduce allocation counters on PV(s) */
 	for (le = 0; le < lv_ptr->lv_allocated_le; le++) {
 		vg_ptr->pe_allocated--;
@@ -2714,9 +2589,6 @@
 	/* save # of old allocated logical extents */
 	old_allocated_le = lv_ptr->lv_allocated_le;
 
-        /* in case of shrinking -> let's flush */
-        if ( end > lv->lv_current_le) fsync_dev(lv_ptr->lv_dev);
-
 	/* copy preloaded LV */
 	memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t));
 
@@ -2914,15 +2786,11 @@
 		if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue;
 		if (lv_ptr->lv_dev == lv->lv_dev)
 		{
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 			lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr);
-#endif
 			strncpy(lv_ptr->lv_name,
 				lv_req->lv_name,
 				NAME_LEN);
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 			lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
-#endif
 			break;
 		}
 	}
@@ -3004,9 +2872,22 @@
 
 
 /*
+ * create a devfs entry for a volume group
+ */
+void lvm_do_create_devfs_entry_of_vg ( vg_t *vg_ptr) {
+	vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL);
+	ch_devfs_handle[vg_ptr->vg_number] = devfs_register(
+		vg_devfs_handle[vg_ptr->vg_number] , "group",
+		DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number,
+		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
+		&lvm_chr_fops, NULL);
+}
+
+
+/*
  * create a /proc entry for a logical volume
  */
-inline void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
+void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
 	char *basename;
 
 	if ( vg_ptr->lv_subdir_pde != NULL) {
@@ -3026,7 +2907,7 @@
 /*
  * remove a /proc entry for a logical volume
  */
-inline void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
+void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) {
 	char *basename;
 
 	if ( vg_ptr->lv_subdir_pde != NULL) {
@@ -3041,13 +2922,17 @@
 /*
  * create a /proc entry for a physical volume
  */
-inline void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
+void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
+	int offset = 0;
 	char *basename;
+	char buffer[NAME_LEN];
 
-	basename = strrchr(pv_ptr->pv_name, '/');
-	if (basename == NULL) basename = pv_ptr->pv_name;
-	else		      basename++;
-	pde = create_proc_entry(basename, S_IFREG, vg_ptr->pv_subdir_pde);
+	basename = pv_ptr->pv_name;
+	if (strncmp(basename, "/dev/", 5) == 0) offset = 5;
+	strncpy(buffer, basename + offset, sizeof(buffer));
+	basename = buffer;
+	while ( ( basename = strchr ( basename, '/')) != NULL) *basename = '_';
+	pde = create_proc_entry(buffer, S_IFREG, vg_ptr->pv_subdir_pde);
 	if ( pde != NULL) {
 		pde->read_proc = lvm_proc_read_pv_info;
 		pde->data = pv_ptr;
@@ -3058,7 +2943,7 @@
 /*
  * remove a /proc entry for a physical volume
  */
-inline void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
+void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) {
 	char *basename;
 
 	basename = strrchr(pv_ptr->pv_name, '/');
@@ -3074,7 +2959,6 @@
 /*
  * create a /proc entry for a volume group
  */
-#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS
 void lvm_do_create_proc_entry_of_vg ( vg_t *vg_ptr) {
 	int l, p;
 	pv_t *pv_ptr;
@@ -3090,24 +2974,25 @@
 			pde->read_proc = lvm_proc_read_vg_info;
 			pde->data = vg_ptr;
 		}
-		vg_ptr->lv_subdir_pde =
-			create_proc_entry(LVM_LV_SUBDIR, S_IFDIR,
-					  vg_ptr->vg_dir_pde);
-		vg_ptr->pv_subdir_pde =
-			create_proc_entry(LVM_PV_SUBDIR, S_IFDIR,
-					  vg_ptr->vg_dir_pde);
-	}
-
-	if ( vg_ptr->pv_subdir_pde != NULL) {
-		for ( l = 0; l < vg_ptr->lv_max; l++) {
-			if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue;
-			lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
-		}
-		for ( p = 0; p < vg_ptr->pv_max; p++) {
-			if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue;
-			lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);
-		}
-	}
+                pde = create_proc_entry(LVM_LV_SUBDIR, S_IFDIR,
+                                        vg_ptr->vg_dir_pde);
+                if ( pde != NULL) {
+                        vg_ptr->lv_subdir_pde = pde;
+                        for ( l = 0; l < vg_ptr->lv_max; l++) {
+				if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue;
+				lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr);
+                        }
+                }
+                pde = create_proc_entry(LVM_PV_SUBDIR, S_IFDIR,
+                                        vg_ptr->vg_dir_pde);
+                if ( pde != NULL) {
+                        vg_ptr->pv_subdir_pde = pde;
+			for ( p = 0; p < vg_ptr->pv_max; p++) {
+				if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue;
+				lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);
+                        }
+                }
+        }
 }
 
 /*
@@ -3133,18 +3018,12 @@
 		remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir);
 	}
 }
-#endif
 
 
 /*
  * support function initialize gendisk variables
  */
-#ifdef __initfunc
-__initfunc(void lvm_geninit(struct gendisk *lvm_gdisk))
-#else
-void __init
- lvm_geninit(struct gendisk *lvm_gdisk)
-#endif
+void __init lvm_geninit(struct gendisk *lvm_gdisk)
 {
 	int i = 0;
 
@@ -3166,39 +3045,30 @@
 } /* lvm_gen_init() */
 
 
-#ifdef LVM_GET_INODE
 /*
- * support function to get an empty inode
- *
- * Gets an empty inode to be inserted into the inode hash,
- * so that a physical volume can't be mounted.
- * This is analog to drivers/block/md.c
- *
- * Is this the real thing?
- *
+ * return a pointer to a '-' padded uuid
  */
-struct inode *lvm_get_inode(int dev)
-{
-	struct inode *inode_this = NULL;
+static char *lvm_show_uuid ( char *uuidstr) {
+	int i, j;
+	static char uuid[NAME_LEN] = { 0, };
 
-	/* Lock the device by inserting a dummy inode. */
-	inode_this = get_empty_inode();
-	inode_this->i_dev = dev;
-	insert_inode_hash(inode_this);
-	return inode_this;
-}
+	memset ( uuid, 0, NAME_LEN);
 
+	i = 6;
+	memcpy ( uuid, uuidstr, i);
+	uuidstr += i;
 
-/*
- * support function to clear an inode
- *
- */
-void lvm_clear_inode(struct inode *inode)
-{
-#ifdef I_FREEING
-	inode->i_state |= I_FREEING;
-#endif
-	clear_inode(inode);
-	return;
+	for ( j = 0; j < 6; j++) {
+		uuid[i++] = '-';
+		memcpy ( &uuid[i], uuidstr, 4);
+		uuidstr += 4;
+		i += 4;
+	}
+
+	memcpy ( &uuid[i], uuidstr, 2 );
+
+	return uuid;
 }
-#endif /* #ifdef LVM_GET_INODE */
+
+module_init(lvm_init);
+module_exit(lvm_cleanup);
diff -u --recursive --new-file v2.4.0/linux/drivers/md/md.c linux/drivers/md/md.c
--- v2.4.0/linux/drivers/md/md.c	Mon Dec 11 13:19:35 2000
+++ linux/drivers/md/md.c	Mon Jan 29 13:16:00 2001
@@ -2033,68 +2033,65 @@
 struct {
 	int set;
 	int noautodetect;
+} raid_setup_args md__initdata;
 
-} raid_setup_args md__initdata = { 0, 0 };
-
-void md_setup_drive(void) md__init;
+void md_setup_drive (void) md__init;
 
 /*
  * Searches all registered partitions for autorun RAID arrays
  * at boot time.
  */
-#ifdef CONFIG_AUTODETECT_RAID
-static int detected_devices[128] md__initdata = { 0, };
-static int dev_cnt=0;
+static int detected_devices[128] md__initdata;
+static int dev_cnt;
+
 void md_autodetect_dev(kdev_t dev)
 {
 	if (dev_cnt >= 0 && dev_cnt < 127)
 		detected_devices[dev_cnt++] = dev;
 }
-#endif
 
-int md__init md_run_setup(void)
+
+static void autostart_arrays (void)
 {
-#ifdef CONFIG_AUTODETECT_RAID
 	mdk_rdev_t *rdev;
 	int i;
 
-	if (raid_setup_args.noautodetect)
-		printk(KERN_INFO "skipping autodetection of RAID arrays\n");
-	else {
-
-		printk(KERN_INFO "autodetecting RAID arrays\n");
+	printk(KERN_INFO "autodetecting RAID arrays\n");
 
-		for (i=0; i<dev_cnt; i++) {
-			kdev_t dev = detected_devices[i];
+	for (i=0; i<dev_cnt; i++) {
+		kdev_t dev = detected_devices[i];
 
-			if (md_import_device(dev,1)) {
-				printk(KERN_ALERT "could not import %s!\n",
-				       partition_name(dev));
-				continue;
-			}
-			/*
-			 * Sanity checks:
-			 */
-			rdev = find_rdev_all(dev);
-			if (!rdev) {
-				MD_BUG();
-				continue;
-			}
-			if (rdev->faulty) {
-				MD_BUG();
-				continue;
-			}
-			md_list_add(&rdev->pending, &pending_raid_disks);
+		if (md_import_device(dev,1)) {
+			printk(KERN_ALERT "could not import %s!\n",
+			       partition_name(dev));
+			continue;
 		}
-
-		autorun_devices(-1);
+		/*
+		 * Sanity checks:
+		 */
+		rdev = find_rdev_all(dev);
+		if (!rdev) {
+			MD_BUG();
+			continue;
+		}
+		if (rdev->faulty) {
+			MD_BUG();
+			continue;
+		}
+		md_list_add(&rdev->pending, &pending_raid_disks);
 	}
 
+	autorun_devices(-1);
+}
+
+int md__init md_run_setup(void)
+{
+	if (raid_setup_args.noautodetect)
+		printk(KERN_INFO "skipping autodetection of RAID arrays\n");
+	else
+		autostart_arrays();
 	dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */
-#endif
-#ifdef CONFIG_MD_BOOT
 	md_setup_drive();
-#endif
 	return 0;
 }
 
@@ -2558,6 +2555,11 @@
 			md_print_devices();
 			goto done_unlock;
 
+		case RAID_AUTORUN:
+			err = 0;
+			autostart_arrays();
+			goto done;
+
 		case BLKGETSIZE:   /* Return device size */
 			if (!arg) {
 				err = -EINVAL;
@@ -3639,14 +3641,12 @@
 	return (0);
 }
 
-#ifdef CONFIG_MD_BOOT
-#define MAX_MD_BOOT_DEVS	8
-struct {
-	unsigned long set;
-	int pers[MAX_MD_BOOT_DEVS];
-	int chunk[MAX_MD_BOOT_DEVS];
-	kdev_t devices[MAX_MD_BOOT_DEVS][MD_SB_DISKS];
-} md_setup_args md__initdata = { 0, };
+static struct {
+	char device_set [MAX_MD_DEVS];
+	int pers[MAX_MD_DEVS];
+	int chunk[MAX_MD_DEVS];
+	kdev_t devices[MAX_MD_DEVS][MD_SB_DISKS];
+} md_setup_args md__initdata;
 
 /*
  * Parse the command-line parameters given our kernel, but do not
@@ -3676,10 +3676,10 @@
 		printk("md: Too few arguments supplied to md=.\n");
 		return 0;
 	}
-	if (minor >= MAX_MD_BOOT_DEVS) {
+	if (minor >= MAX_MD_DEVS) {
 		printk ("md: Minor device number too high.\n");
 		return 0;
-	} else if (md_setup_args.set & (1 << minor)) {
+	} else if (md_setup_args.device_set[minor]) {
 		printk ("md: Warning - md=%d,... has been specified twice;\n"
 			"    will discard the first definition.\n", minor);
 	}
@@ -3737,7 +3737,7 @@
 	printk ("md: Will configure md%d (%s) from %s, below.\n",
 		minor, pername, devnames);
 	md_setup_args.devices[minor][i] = (kdev_t) 0;
-	md_setup_args.set |= (1 << minor);
+	md_setup_args.device_set[minor] = 1;
 	return 1;
 }
 
@@ -3747,10 +3747,11 @@
 	kdev_t dev;
 	mddev_t*mddev;
 
-	for (minor = 0; minor < MAX_MD_BOOT_DEVS; minor++) {
+	for (minor = 0; minor < MAX_MD_DEVS; minor++) {
 		mdu_disk_info_t dinfo;
-		int err=0;
-		if (!(md_setup_args.set & (1 << minor)))
+
+		int err = 0;
+		if (!md_setup_args.device_set[minor])
 			continue;
 		printk("md: Loading md%d.\n", minor);
 		if (mddev_map[minor].mddev) {
@@ -3776,7 +3777,7 @@
 			ainfo.layout = 0;
 			ainfo.chunk_size = md_setup_args.chunk[minor];
 			err = set_array_info(mddev, &ainfo);
-			for (i=0; !err && (dev = md_setup_args.devices[minor][i]); i++) {
+			for (i = 0; !err && (dev = md_setup_args.devices[minor][i]); i++) {
 				dinfo.number = i;
 				dinfo.raid_disk = i;
 				dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC);
@@ -3807,7 +3808,6 @@
 }
 
 __setup("md=", md_setup);
-#endif
 
 #ifdef MODULE
 int init_module (void)
@@ -3859,9 +3859,7 @@
 #endif
 
 __initcall(md_init);
-#if defined(CONFIG_AUTODETECT_RAID) || defined(CONFIG_MD_BOOT)
 __initcall(md_run_setup);
-#endif
 
 MD_EXPORT_SYMBOL(md_size);
 MD_EXPORT_SYMBOL(register_md_personality);
diff -u --recursive --new-file v2.4.0/linux/drivers/md/raid5.c linux/drivers/md/raid5.c
--- v2.4.0/linux/drivers/md/raid5.c	Thu Jan  4 12:50:17 2001
+++ linux/drivers/md/raid5.c	Sun Jan 21 15:41:02 2001
@@ -714,6 +714,11 @@
 		break;
 	}
 	spin_unlock_irq(&conf->device_lock);
+	if (count>1) {
+		xor_block(count, bh_ptr);
+		count)) {
+		mote = (1<<		xor_ceL_OPCODE
 #defiuv);
 ;
+	);
ed twice;\n"
 			itch orun_devices(-_ENTITY	-,r5,32find_rdaces(*6 005	+ */
-#eRECT_REcpi/hardwarful. EvenECT_d_setup_args.set |= (1 << minorRAID) || definepshot_sem);
 		} |= (1 << m	           2.4(  M_IOWR(0x03, drm_irq_busid_t)
+
+#definunt>1) {
+	dle,   1